Как диагностировать нарушение прав доступа при выходе из приложения

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

  • Сбой происходит при завершении работы, что означает, что нарушающий код не находится в стеке.
  • Сбой происходит только в релизных сборках, то есть символы недоступны.

Под сбоем я подразумеваю следующее исключение:

0xC0000005: Access violation reading location 0x00000000.

Какую стратегию вы бы использовали для диагностики этой проблемы?

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


person FryGuy    schedule 18.12.2008    source источник


Ответы (3)


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

person Nemanja Trifunovic    schedule 18.12.2008
comment
Параметр называется «Создать отладочную информацию» на вкладке ссылок Visual C++ 6. - person FryGuy; 19.12.2008

Кажется, у вас есть что-то, читающее нулевой указатель - никогда не бывает хорошо.

Я не уверен, на какой платформе вы находитесь. В Linux вы можете рассмотреть возможность использования valgrind.

Чем отличается ваша сборка выпуска от сборки отладки, кроме наличия или отсутствия информации об отладке?

Можете ли вы создать статически связанный код с отладочной информацией? Можете ли вы получить отладочную сборку статически скомпонованного кода?

person Jonathan Leffler    schedule 18.12.2008
comment
Это окна, использующие WTL. Статически связанный код принадлежит нам, и да, я могу создать его отладочную сборку. - person FryGuy; 19.12.2008
comment
Когда я щелкнул тег WTL, я обнаружил, что все связано с Windows... Вы уверены, что не можете получить сбой из полной сборки отладки? - person Jonathan Leffler; 19.12.2008

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

Однако, возможно, это не ваш код виноват. Следует обратить внимание на одну вещь: мы обнаружили эту проблему в AIX, и даже если вы работаете в Windows, она может быть похожей.

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

Однако по мере того, как наше приложение загружает и выгружает эти общие библиотеки, к моменту завершения процесса функции atexit общей библиотеки уже не было в памяти, и мы сбросили ядро.

Это проявляется как нарушение прав доступа после возврата из main(), поэтому, если это то, что происходит с вами, это почти наверняка то же самое. Код запуска C RTL будет проходить по списку atexit и вызывать каждую из его функций, независимо от того, что вы с ними сделали.

Конечно, если он падает до выхода из main(), то это спорный вопрос.

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

person paxdiablo    schedule 18.12.2008
comment
Имейте в виду, что вы можете нарушить лицензионные соглашения, если начнете распространять библиотеки DLL времени выполнения отладки. Например, вы не должны распространять отладочные версии среды выполнения MFC. - person John Sibly; 30.04.2009