Question

I have an application that requests data from a database triggered by a timer on a form. If there is an error (the connection to the database is lost), I sometimes I get the expected exception (EIBO_ISCError) and sometimes I get an access violation in RtlLeaveCriticalSection of ntdll.dll. Here is the corresponing Eurekalog stack:

------------------------------------------------------------------------------------------------------
|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] |
------------------------------------------------------------------------------------------------------

The code, which is executed, is nothing special. It boils down to:

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

when creating the form and

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

in the OnTimer event of the MDI form.

The code line in IBObjects that is called in DoHandleError is

raise EIBO_ISCError.CreateISC( ... );

The underlaying exception is likely to be caused by a lost database connection in qry.Open. What I want to know is, which circumstances (read defects in my code) can lead to the behaviour, that sometimes this exception is handled as expected (EIBO_ISCError in Eurekalog) and sometimes the same exception leads to an access violation in RtlLeaveCriticalSection.

Was it helpful?

Solution

It looks like you have heap corruption. Somewhere, your program has written to memory that you're not supposed to write to.

That might mean you've written to a critical-section data structure belonging to the heap, but it might mean you've written somewhere else that caused the memory manager to think there's a critical-section object where there really isn't one.

The stack trace suggests you're still getting the usual exception you expected to get, but in attempting to handle that exception, something goes wrong.

You could try using the debugger to inspect other memory near where the invalid read occurs. See whether there are any strings or numbers you recognize from your program. They could indicate which section of code is writing where it shouldn't.

OTHER TIPS

From the comments, for reference:

The cause of this access violation was, that I freed an exception that occured while handling an other exception (like originally suggested here).

Citation from the comments:

you should never free an exception, ever

The exception was handled normally if during the handling of the original exception no other exception occured. If an other exception occured I got the access violation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top