Как узнать, какой код вызывает уже выгруженный модуль? - PullRequest
2 голосов
/ 01 августа 2011

Я получил типичное нарушение прав доступа:

access violation at 0x4ebb7456: read of address 0x4ebb7456

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

Основной поток работает System.FinalizeUnits во время исключения.

Я обнаружил, что адрес принадлежит области памяти, в которую загружен gdiplus.dll.

Проблема исчезнет, ​​если я добавлю LoadLibrary('gdiplus.dll') вызов в файл dpr без вызова FreeLibrary для возвращаемого дескриптора, таким образом gdiplus.dll не выгружается во время выполнения разделов финализации.

Какузнать, какая часть программы создает поток, приводящий к нарушению доступа?

Есть ли способ идентифицировать код, который вызывает в освобожденное пространство памяти?

FastMM и madExceptНебольшая помощь, окно отчета об ошибках MadExcept появляется, но сразу же снова закрывается и не записывает файл журнала.

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

Ответы [ 2 ]

3 голосов
/ 01 августа 2011

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

Что касается того, как это сделать, я бы использовал точки останова отладчика.,Прежде всего, я бы установил точку останова на реализацию CreateThread в Windows.pas и запустил с отладочными DCU.Посмотрите, сработает ли эта точка останова во время выключения.

Если она не взломается там во время выключения, тогда поток создается не-Delphi-кодом.Мой следующий шаг - открыть представление CPU и перейти к CreateThread.Разборка для CreateThread начнется с инструкции JMP.Шагните в это, и вы будете на kernel32.CreateThread.Теперь установите здесь точку останова и посмотрите, что такое стек вызовов, когда вы запускаете его во время выключения.

2 голосов
/ 01 августа 2011

Я бы нашел модуль, который загружает библиотеку (возможно, это компонент, который вы используете), и добавил бы его в начало (или почти вверху) файла вашего проекта.Это гарантирует, что оно будет выгружено позже при завершении работы вашего приложения, и должно предотвратить AV.

Так, например, если вы используете GdiPlus , вы получите что-то вроде этого:

program MyProgram;

uses
  FastMM4,
  GdiPlus,  // <=== this line inserted
  Windows,
  Forms,
  Controls,
  Classes,

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

...