Delphi: как я могу отладить нарушения доступа при закрытии моего приложения?

#delphi #access-violation

#delphi #нарушение доступа

Вопрос:

Я использую Delphi 6, и у меня есть приложение, которое при закрытии выдает ошибки нарушения доступа. Мы используем EurekaLog, поэтому я получаю трассировки стека для отладки, но ошибки, похоже, каждый раз возникают случайным образом в разных блоках, но всегда, когда что-то освобождается в разделе финализации.

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

[Редактировать:]Извините, если я был неясен, возможно, лучшим вопросом было бы: какое лучшее место для начала отладки с точками останова, если я хочу только пройти через разделы завершения? Похоже, ошибки возникают в сторонних компонентах, которые мы используем (библиотека devexpress dx / cxgrid), поэтому я хотел бы начать отладку в своем коде практически в последний момент, прежде чем Delphi начнет вызывать процедуры завершения в других подразделениях.

Комментарии:

1. Отлаживайте как обычно. Возможно, вы захотите использовать отладочные DCU, если AVS возникают в единицах RTL / VCL. Установите точки останова в разделах завершения и шага. На самом деле вам не нужно устанавливать точки останова, вы можете просто запустить отладчик и организовать, чтобы исключения запускали точку останова.

2. Диспетчер памяти FastMM также является бесценным инструментом для отслеживания утечек памяти. fastmm .

3. У вас много форм? Попробуйте удалить их из файла .dpr после вызова Application.Run . Посмотрите, поможет ли это. Если вы позволите приложению делать это, вы можете столкнуться с некоторыми сложными ошибками VCL (но я не уверен, что они распространяются вплоть до D6).

4. @David у вас есть дополнительная информация или ссылка, касающиеся этих ошибок с уничтожением формы? Недавно я отлаживал некоторую ситуацию, в которой это могло сыграть роль…

5. Я ввел отчет о контроле качества. Не могу вспомнить номер. Поиск по моему имени даст вам это.

Ответ №1:

Это не так много, но если бы мне пришлось догадываться, основываясь на прошлом опыте… вы используете пакеты или библиотеки COM? Если у вас есть глобальная переменная, которая является интерфейсом, или объект, класс которого объявлен в БПЛ, и вы выгружаете DLL / БПЛ перед очисткой объекта / интерфейса, вы получите нарушения доступа, потому что ваш код пытается выполнить поиск VMT в адресном пространстве, которое больше не являетсясопоставлено с приложением.

Проверьте это и убедитесь, что вы очистили все такие переменные перед началом завершения.

Комментарии:

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

2. @Rob: Ооооочень много настроек точек останова, нажатия F7 и F8 и пристального внимания к тому, что происходит. В последний раз у меня была эта проблема на D2010, до того, как они начали отправлять отладочные версии системных DCP. Это было не весело, поверьте мне.

3. @Rob: За исключением того, что это подсказывает, на чем сосредоточиться, и я бы согласился с Мейсоном из прошлого опыта, что COM-объекты могут сделать это с вами.

4. @MasonWheeler спасибо — я немного обновил вопрос. В написанном мной коде я не использую пакеты или библиотеки COM, но я использую сторонний компонент, который может быть, я не уверен.

Ответ №2:

Когда приложение завершает работу, не освобождайте вещи в разделе завершения.

1) Когда приложение завершает работу, Windows освобождает всю память приложения. Вам не обязательно это делать.

2) Когда приложение завершает работу, память освобождается, а инфраструктура выгружается. Вы не можете вызвать код для закрытия или освобождения объектов, потому что этот код, возможно, уже выгружен. Вы не можете получить доступ к указателям на память, потому что эти указатели, возможно, уже были выпущены.

3) Когда вы пытаетесь освободить что-то в разделе завершения во время завершения работы приложения, вы можете получить сбои, которые препятствуют завершению вашего кода, тем самым предотвращая завершение работы приложения, вызывая зависание приложения и потерю памяти. Это то, что вы пытались предотвратить в первую очередь. Не делайте этого.

Хорошо, когда вы работаете на Win95 / 98 или используете внешние процессы, в некоторых случаях вам может потребоваться освободить общие ресурсы и уведомить те внешние процессы, которые вы завершаете. Кроме того, теперь все происходит автоматически.