【发布时间】:2015-01-31 02:15:28
【问题描述】:
我在一个 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)时,调试器只是停止:它不会继续到except块,也不会到FinalizeUnits()函数的末尾(我已经设置了断点)。
顺便说一句:这怎么可能?我认为在任何情况下都必须调用 except 块(或它之后的行)。
注释:
- 当我手动避免这个特殊调用时,所有其他功能都正常执行。
- 当我进入有问题的
TProc时,我最终会进入TCriticalSection.Enter(然后是Acquire-FSection.Enter-EnterCriticalSection-WSACleanup)
WSACleanup 调用的更多信息:我使用第 3 方库 UniDAC,它打开与数据库的 TCP/IP 连接 - 我认为这个库在它的最终确定部分之一调用 WSACleanup(但我没有没有这个源代码)。
奇怪的是,当调试器位于WSACleanup 行时:
function WSACleanup; external winsocket name 'WSACleanup';
并且我想跳过它(即 F8),调试器只是停止(好像应用程序已正常退出) - 但它应该继续 FinalizeUnits 中的循环:这怎么可能?也就是说,如果它是一个死锁,它不会停止,而是永远挂起,对吧?
问题是:如何调试这个问题?死锁是否可能导致此问题(即调试器刚刚停止)?
【问题讨论】:
-
" .. 最终进入 TCriticalSection.Enter " - 它不会从那里去任何地方?
-
"我想到了 except 块" 你可能想到了 finally 块。我看到你有一个很好的建议的答案,并且知道它试图调试到 FinalizeUnits 是多么痛苦,我只是想检查你是否知道你可以在断点上设置“通过计数”正确-单击装订线中的红点并转到“断点属性...”
-
启用 debug dcus 并找出问题出在哪个单元。然后找出出现死锁的原因。
-
@SertacAkyuz:还有一些电话(现在显示在问题中)
-
@MartynA:对不起,我关于 except 块的陈述不清楚:我的意思是,它应该进入 except 块或它之后的行(我现在已经更新了问题) - 但是正如大卫赫弗南指出的那样,这可能是由于僵局。如果“Count = 363”,我已使用断点属性停止 - 感谢您的提示。
标签: delphi debugging dll dcom finalize