如何解释RtlLeaveCriticalSection中的访问冲突

时间:2014-03-25 09:57:27

标签: delphi error-handling stack-trace delphi-2006

我有一个应用程序,它从表单上的计时器触发的数据库中请求数据。如果有错误(与数据库的连接丢失),我有时会得到预期的异常(EIBO_ISCError),有时我会在ntdll.dll的RtlLeaveCriticalSection中获得访问冲突。这是相应的Eurekalog堆栈:

------------------------------------------------------------------------------------------------------
|Adresse |Modul         |Unit               |Klasse             |Prozedur/Methode          |Zeile    |
------------------------------------------------------------------------------------------------------
|Laufender Thread: ID=1320; Priorität=0; Klasse=; [Haupt Thread]                                     |
|----------------------------------------------------------------------------------------------------|
|76FD2280|ntdll.dll     |                   |                   |RtlLeaveCriticalSection   |         |
|76FDE0ED|ntdll.dll     |                   |                   |RtlAllocateHeap           |         |
|76FE6CC5|ntdll.dll     |                   |                   |LdrUnlockLoaderLock       |         |
|7552EF19|KERNELBASE.dll|                   |                   |VirtualQueryEx            |         |
|7552EF02|KERNELBASE.dll|                   |                   |VirtualQueryEx            |         |
|7552EFE6|KERNELBASE.dll|                   |                   |VirtualQuery              |         |
|76FC012E|ntdll.dll     |                   |                   |KiUserExceptionDispatcher |         |
|0069D997|Program.exe   |IBODataset.pas     |TIBOInternalDataset|DoHandleError             |8407[23] |
|0063B3F7|Program.exe   |IB_Components.pas  |TIB_Session        |DoHandleError             |13181[2] |
|0068B36C|Program.exe   |IB_Session.pas     |TIB_SessionBase    |HandleException           |1442[58] |
|0068B03C|Program.exe   |IB_Session.pas     |TIB_SessionBase    |HandleException           |1384[0]  |
|0064EE74|Program.exe   |IB_Components.pas  |TIB_Statement      |API_Execute               |22927[14]|
|0064EE10|Program.exe   |IB_Components.pas  |TIB_Statement      |API_Execute               |22913[0] |
|00655D1D|Program.exe   |IB_Components.pas  |TIB_Dataset        |SysExecSelect             |26432[1] |
|0064DA60|Program.exe   |IB_Components.pas  |TIB_Statement      |SysExecStatement          |22259[9] |
|0064D7A1|Program.exe   |IB_Components.pas  |TIB_Statement      |SysExecute                |22173[12]|
|0064D708|Program.exe   |IB_Components.pas  |TIB_Statement      |SysExecute                |22161[0] |
|00655A9F|Program.exe   |IB_Components.pas  |TIB_Dataset        |SysExecute                |26373[7] |
|00655210|Program.exe   |IB_Components.pas  |TIB_Dataset        |SysOpen                   |26160[23]|
|006550F8|Program.exe   |IB_Components.pas  |TIB_Dataset        |SysOpen                   |26137[0] |
|006994E5|Program.exe   |IBODataset.pas     |TIBODataset        |DoBeforeOpen              |6312[17] |
|0061FBEA|Program.exe   |mvdb.pas           |TImvDatabase       |QueryRun                  |1393[10] |
...
|00B1D440|Program.exe   |StartDialogForm.pas|TFormStartDialog   |UpdateStartBar            |494[0]   |
|00B1D4C3|Program.exe   |StartDialogForm.pas|TFormStartDialog   |TimerExBarTimer           |521[6]   |
|76667BC5|USER32.dll    |                   |                   |DispatchMessageA          |         |
|76667BBB|USER32.dll    |                   |                   |DispatchMessageA          |         |
|00BF1178|Program.exe   |Program.dpr        |                   |                          |884[399] |
------------------------------------------------------------------------------------------------------

执行的代码没什么特别的。归结为:

qry := TIBOQuery.Create(nil);      //IBObjects
qry.SQL := 'SELECT COUNT(IDX) FROM TABLE';
qry.Prepare;

创建表单时

qry.Open;       //<-- Exception
TotalCount := qry.Fields[0].AsVariant;
qry.Close;

在MDI表单的OnTimer事件中。

在DoHandleError中调用的IBObjects中的代码行是

raise EIBO_ISCError.CreateISC( ... );

底层异常可能是由qry.Open中丢失的数据库连接引起的。我想知道的是,哪些情况(读取我的代码中的缺陷)可能导致行为,有时这个异常按预期处理(Eurekalog中的EIBO_ISCError),有时相同的异常会导致RtlLeaveCriticalSection中的访问冲突。

2 个答案:

答案 0 :(得分:3)

看起来你有堆腐败。在某个地方,你的程序写入了你不应该写的内存。

这可能意味着您已经写入属于堆的关键部分数据结构,但这可能意味着您已经在其他地方编写了导致内存管理器认为存在的关键 - 部分对象,其中没有一个。

堆栈跟踪表明您仍然得到了预期会得到的常见异常,但在尝试处理该异常时,出现了问题。

您可以尝试使用调试器检查发生无效读取的位置附近的其他内存。查看您是否从程序中识别出任何字符串或数字。他们可以指出代码的哪个部分正在编写它不应该写的地方。

答案 1 :(得分:0)

来自评论,供参考:

此访问冲突的原因是,我释放了处理其他异常时发生的异常(如最初建议的here)。

来自评论的引文:

  

你永远不应该免除例外

如果在处理原始异常期间没有发生其他异常,则异常处理正常。如果发生其他异常,我收到了访问冲突。