Есть ли способ проверить, болтается ли указатель? - PullRequest
11 голосов
/ 05 октября 2011

У меня есть код, где я использую указатель для доступа к некоторому блоку данных.В некоторых редких случаях несколько элементов блока данных пусты, и в результате указатель становится висящим.На самом деле, я получаю правильный указатель, но программа вылетает при попытке что-то сделать с указателем.

Обычный совет - избегать такого использования.Но, к сожалению, используемая мной среда требует использования методов доступа к данным такого типа.

Есть ли способ, которым я могу "проверить", является ли указатель недействительным, прежде чем выполнять какие-либо операции с ним?Проверка, что указатель не равен NULL, не сработала, очевидно.Я также попробовал это:

try
{
    CString csClassName = typeid(*pMyPointer).name();  // Check error condition
    // The line below fails due to dangling pointer (data block is not valid).
    hr = pMyPointer->MyPointerMethod(); 
}
catch(bad_typeid)
{
    return E_FAIL;
}
catch(...)
{
    return E_FAIL;
}

Это правильный путь?

Ответы [ 4 ]

7 голосов
/ 05 октября 2011

Я думаю, что вы смотрите в неправильном направлении. Возможно, у вас есть ошибка, из-за которой вы неправильно инициализируете указатели, слишком рано удаляете объекты и пытаетесь повторно использовать указатель после того, как он был удален или что-то в этом роде. Если это так, вам следует сосредоточиться на определении причины и устранении ошибки, а не пытаться найти способ скрыть ошибку.

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

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

Теперь, на первоначальном вопросе о том, как проверить, болтается ли указатель, вы не можете сделать это в программе, но вы можете запустить вашу программу в отладчиках памяти (valgrind в linux, Purify или ряд других в linux), и инструмент сможет помочь вам определить, был ли указатель никогда не инициализирован или вы освободили память для системы перед неправильным использованием.

7 голосов
/ 05 октября 2011

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

3 голосов
/ 05 октября 2011

Да, вы можете использовать умные указатели .

2 голосов
/ 09 ноября 2014

Вам не нужны умные указатели. Это всего лишь один из возможных подходов к решению этой проблемы.

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

...