Member 13729319 Ответов: 3

C++ wild pointer judge


Код как:
int main()
{
   int* p = new int;
   int* p2 = p;

   delete p2;
   p2 = NULL;

   return 0;
}

Итак, вопрос в том, является ли переменная p диким указателем?

Что я уже пробовал:

typedef struct List_Tags
{
    int data;
    struct List_Tags *pNext;
}List_T;
void DeleteList(List_T* pHead)
{
    while(pHead)
    {
        List_T* tmp = pHead->pNext;
        delete pHead;
        pHead = tmp;
    }
}

Итак, если вы удалите список вот так, не будет ли там много диких указателей?

3 Ответов

Рейтинг:
20

Stefan_Lang

Указатель p в первом примере болтается, как уже объяснялось.

Функция DeleteList() внутренне это нормально, но все равно может быть проблематично, потому что вызывающий объект все еще содержит ненулевой указатель на начало удаленного списка, который теперь указывает на недействительную память:

void foo() {
    List_T* my_list = new List_T;
    my_list->data = 42;
    my_list->pNext = nullptr;
    if (my_list)
        std::cout << my_list->data; // prints 42
    DeleteList(my_list);
    if (my_list)
        std::cout << my_list->data; // undefined behaviour
}

Если вы хотите очистить и этот указатель, вы должны передать его по ссылке и установить значение 0:
void DeleteList(List_T*& pHead)
{
    while(pHead)
    {
        List_T* tmp = pHead->pNext;
        delete pHead;
        pHead = tmp;
    }
    pHead = nullptr;
}

При таком изменении функция foo() выше не будет пытаться получить доступ к недействительному указателю.


Рейтинг:
2

Mircea Neacsu

p это действительно дикий указатель, потому что он указывает на пространство, которое было освобождено (через p2 указатель).
Однако код для удаления связанного списка вполне в порядке. tmp содержит постоянно действующий указатель на следующий элемент в списке. Первый элемент в списке, на который указывает pHead, освобождается и сразу же после следующего элемента становится головой.


Member 13729319

Код как :
DeleteList(pList);

Но разве функция DeleteList не то же самое, что удаление только P2? Станет ли переменная pList диким указателем?

Rick York

Нет, DeleteList пересекает список и удаляет все выделенные объекты. pList укажет на данные, которые были освобождены и не были обнулены, так что да.

Рейтинг:
2

Mircea Neacsu

Вы правы, pList становится диким указателем. Но в этом смысле каждый указатель становится диким, когда объект, на который он указывает, освобождается.

Как предложил Стефан, pHead может передаваться как ссылка на указатель, так что когда DeleteList возвращается pHead является нулевым. Нулевой указатель по-прежнему является диким указателем (указывает на недопустимый адрес), но я бы назвал его "контролируемая дикими Пуэнтr" потому что вы можете проверить его, чтобы убедиться, что он действителен. Сравните это с ситуацией, когда p где вы не можете знать, указывает ли он на допустимый блок или нет.

Другое решение состоит в том, чтобы избегать работы с указателями и освобождать пространство только тогда, когда объект выходит из области видимости (в деструкторе). В зависимости от вашей проблемы это не всегда работает.