C ++ удалить указатель с действительным адресом - PullRequest
3 голосов
/ 08 августа 2011

Я использую библиотеку Poco C ++ и вызываю странную проблему.Poco использует собственный класс общего указателя SharedPtr для внутренних операций с указателем.В моем случае статический объект Poco::SSLManager имеет SharedPtr членов объектов обработчиков сертификатов.Когда выполнение программы заканчивается, статический объект удаляется, и я улавливаю ошибку сегментации.Использует отладчик GDB. Я вижу дамп ядра и не понимаю проблемы.Ошибка сегмента возникает при удалении объекта SharedPtr (простая операция: delete pObj), но объект имеет действительный адрес, например - 0x8fcbed8.

Почему удаление указателя с действительным адресом может вызвать ошибку сегментации?
Это может быть из-за того, что объект создается в ветвленной копии приложения и уничтожается в главной?

Ответы [ 4 ]

11 голосов
/ 08 августа 2011

Действительный адрес - это просто доступный адрес.Это не значит, что он подходит для удаления.Вы можете только delete, что вы получили от new.Если вы не new это, вы не можете delete это.Удаление статического или автоматического объекта является неопределенным поведением, равно как и тем, которое вы можете получить из любого другого источника, кроме new.

0 голосов
/ 12 августа 2011

Это очень сложная проблема, и я не понимаю проблему в полной мере, но я пытаюсь объяснить это и свое решение. Проблема зависит от платформы и возникает только в Gentoo Linux с компилятором gcc 4.5.5 с библиотеками Poco.

У меня есть демон, который использует модули (плагины) для обработки различных запросов. Модули и демон используют одну статическую библиотеку, которая использует библиотеку poco. В статической библиотеке есть код для создания SSL-соединений и в результате создается SSL-менеджер. Статическая библиотека связана с модулем и с deamon.

И после окончания работы Деймона у меня есть ошибка сегментации, которая описана в моем вопросе. Я изменяю статическую библиотеку на разделяемую библиотеку, и проблема исчезла, никаких ошибок сегментов. Все отлично работает.

На самом деле, я не понимаю этого, но, похоже, это ошибка компилятора gcc на gentoo. На других linux с другими gcc все хорошо работает со статической библиотекой.

0 голосов
/ 08 августа 2011

Как сказал другой, это не потому, что ваш указатель выглядит "хорошо", как 0x8fcbed8, что это правильный указатель.

Фактически, если вы используете «delete», указатель сохранит свое значение. Но вы не должны использовать его больше. (Рекомендуется устанавливать его в NULL сразу после удаления, чтобы он показывался «пустым» с помощью отладчика.)

Существует инструмент, который может помочь вам найти, что не так, если вы разрабатываете с Linux. Это Valgrind :

valgrind  your_program  [args]

(просто добавьте «valgrind» перед командой, которую вы обычно запускаете. Установите valgrind, если ее здесь еще нет, должен быть пакет для него в вашем дистрибутиве, поскольку это широко используемый инструмент.)

Затем valgrind проверит вашу программу во время ее работы (немного замедляя) и немедленно сообщит вам, как только вы удалите что-то, что не должны делать. (и много других ошибок)

0 голосов
/ 08 августа 2011

Вы говорите об использовании shared pointer.Если это удаление является последним удалением в pObj, возможно, это последний раз, когда объект удаляется ... и поэтому объект, на который указывает общий указатель, будет окончательно уничтожен.В этом случае вызывается destructor из pObj, и, возможно, оттуда вы получаете ошибку сегмента.

С другой стороны, в зависимости от того, какую реализацию общего указателя использует библиотека Poco, может случиться так, что вы неправильно используетеразделяемый указатель путем вызова удаления на нем.

...