delphi dll-finalization: как отлаживать

У меня проблема в dll (включая COM объект): при выгрузке dll некоторые секции финализации выполняются, а некоторые нет.

в отладчике мне удалось обнаружить проблему в System FinalizeUnits(). псевдокод этой функции - для вашего удобства:

procedure FinalizeUnits;
var
  Count: Integer;
  Table: PUnitEntryTable;
  P: Pointer;
begin
  if InitContext.InitTable = nil then
    exit;
  Count := InitContext.InitCount;
  Table := InitContext.InitTable^.UnitInfo;
  try
    while Count > 0 do
    begin
      Dec(Count);
      InitContext.InitCount := Count;
      P := Table^[Count].FInit;
      if Assigned(P) and Assigned(Pointer(P^)) then
      begin
        // ISSUE: when this is called for item x the debugging just stops
        // breakpoints in the except block or at the end of the function are not reached!
        TProc(P)(); 
      end;
    end;
  except
    FinalizeUnits;  { try to finalize the others }
    raise;
  end;
end;

есть один конкретный вызов завершения, который вызывает проблему:
т. е. InitContext.InitCount составляет около 400, и когда выполняется элемент x (например, 363), отладчик просто останавливается: он не переходит к блоку исключений, а также не доходит до конца функции FinalizeUnits() (где я установил точки останова).
Кстати, как это возможно? Я думал, что блок exclude (или строка после него) должен вызываться в любом случае.

Примечания:

  • когда я вручную избегаю этого специального вызова, все остальные функции выполняются нормально.
  • когда я вступаю в проблемную TProc, я попадаю в TCriticalSection.Enter (затем Acquire - FSection.Enter - EnterCriticalSection - WSACleanup)

еще немного информации о вызове WSACleanup: я использую стороннюю библиотеку UniDAC, которая открывает соединение TCP/IP с базой данных - я думаю, что эта библиотека вызывает WSACleanup в одном из разделов завершения (но у меня нет этого исходного кода). Странно то, что когда отладчик стоит на строке WSACleanup:

function WSACleanup;        external     winsocket name 'WSACleanup';

и я хочу перешагнуть его (т.е. F8), отладчик просто останавливается (как будто приложение завершилось нормально) - но он должен продолжить цикл в FinalizeUnits: как это возможно? т.е. если бы это был тупик, то он бы не остановился, а завис навечно, верно?

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


person TmTron    schedule 02.12.2014    source источник
comment
.. попадают в TCriticalSection.Enter — оттуда никуда не уходит?   -  person Sertac Akyuz    schedule 02.12.2014
comment
Я думал, что блок exclude Вы, вероятно, имеете в виду блок finally. Я вижу, у вас был ответ с хорошим предложением, и, зная, какую боль он пытается отладить в FinalizeUnits, я просто хотел проверить, знаете ли вы, что вы можете установить количество проходов в точке останова, щелкнув правой кнопкой мыши красная точка в желобе и переход к свойствам точки останова...   -  person MartynA    schedule 02.12.2014
comment
Включите отладку dcus и выясните, в каком устройстве проблема. Затем выясните, почему у вас взаимоблокировка.   -  person David Heffernan    schedule 02.12.2014
comment
@SertacAkyuz: есть еще несколько звонков (теперь показано в вопросе)   -  person TmTron    schedule 03.12.2014
comment
@MartynA: извините, мое утверждение о блоке за исключением было неясным: я имел в виду, что он должен идти в блок за исключением или в строку после него (сейчас я обновил вопрос) - но, как указал Дэвид Хеффернан, это может быть из-за тупика. Я использовал свойства точки останова, чтобы остановить, если Count = 363 - спасибо за подсказку.   -  person TmTron    schedule 03.12.2014
comment
@DavidHeffernan: отладка DCU включена, иначе я не мог бы войти в системный блок, верно? Я подумал, может быть, есть простой способ узнать, к какой единице принадлежит функция P — свойство InitContext.InitTable.TypeInfo.UnitNames выглядит многообещающе — но как его использовать?   -  person TmTron    schedule 03.12.2014
comment
AFAICT в стандартных единицах только web.win.sockets завершает winsock (1.1) в разделе финализации.   -  person Sertac Akyuz    schedule 03.12.2014
comment
Что ж, когда вы перейдете к финализации, вы попадете в код этого юнита.   -  person David Heffernan    schedule 05.12.2014
comment
Поскольку это сторонняя библиотека, у меня не было исходного кода. Но тем временем мне удалось сделать очень простой пример, в котором я могу воспроизвести проблему и сообщить об этом в их поддержку. Спасибо за весь вклад здесь.   -  person TmTron    schedule 05.12.2014
comment
обновление: оказалось, что это не проблема сторонней библиотеки, а что-то, связанное с моей машиной разработки. в итоге я полностью переустановил windows, delphi и т.д. и теперь все работает (с тем же исходным кодом на той же машине...)   -  person TmTron    schedule 12.01.2015


Ответы (1)


Попробуйте переключиться в представление ЦП, прежде чем переходить к проблемному TProc с помощью F7. Иногда это может дать вам хорошую подсказку.

Вы также можете попробовать найти адрес "P" в файле карты.

person Sebastian Z    schedule 02.12.2014