#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 или используете внешние процессы, в некоторых случаях вам может потребоваться освободить общие ресурсы и уведомить те внешние процессы, которые вы завершаете. Кроме того, теперь все происходит автоматически.