如何解释访问冲突RtlLeaveCriticalSection(How to explain acc

2019-10-19 16:23发布

我有一个从窗体上的定时器触发一个数据库请求数据的应用程序。 如果有错误(数据库的连接丢失),我有时我得到预期的异常(EIBO_ISCError),有时我ntdll.dll中的RtlLeaveCriticalSection获得访问冲突。 这里是corresponing 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事件。

在IBObjects的代码行,被称作DoHandleError是

raise EIBO_ISCError.CreateISC( ... );

垫层异常可能是由在qry.Open丢失的数据库连接导致的。 我想知道的是,何种情况下(在读我的代码缺陷)可导致行为,有时如预期(EIBO_ISCError在Eurekalog),有时同样的异常会导致访问冲突RtlLeaveCriticalSection这个异常被处理。

Answer 1:

它看起来像你有堆损坏。 冥冥之中,你的程序写入到,你不应该写入内存。

这可能意味着你已经写到属于堆临界区的数据结构,但它可能意味着你已经写了别的地方导致内存管理器认为有一个临界区对象,其中是不是真的有一个。

堆栈跟踪说明你仍然得到你所期望得到的通常的例外,但在试图处理该异常,不顺心的事。

你可以尝试使用调试器来检查,其中无效读附近发生其他内存。 看看是否有你从你的程序识别任何字符串或数字。 他们可以指出哪些代码段是写在那里它不应该。



Answer 2:

从意见,供参考:

此访问冲突的原因是,我释放所发生的同时处理一个其他异常(如最初提出的例外在这里 )。

从注释中引用:

你永远不应该释放一个例外,永远

唯一的例外是原始异常没有其他出现异常的处理过程中,通常若处理。 如果其他出现异常,我得到了访问冲突。



文章来源: How to explain access violation in RtlLeaveCriticalSection