5
votes

As part of Vista certification, Microsoft wants to make sure that an application exits without holding on to a lock (critical section):

TEST CASE 31. Verify application does not break into a debugger with the specified AppVerifier checks (Req:3.2)

As it turns out, network applications built using Delphi 2009 does break into the debugger, which displays unhelpful message as follows:

(1214.1f10): Break instruction exception - code 80000003 (first chance)
eax=00000001 ebx=07b64ff8 ecx=a6450000 edx=0007e578 esi=0017f7e0 edi=80000003
eip=77280004 esp=0017f780 ebp=0017f7ac iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SysWOW64\ntdll.dll - 
ntdll!DbgBreakPoint:
77280004 cc              int     3

After hitting Go button several times, you come across the actual error:

=======================================
VERIFIER STOP 00000212: pid 0x18A4: Freeing virtual memory containing an active critical section. 

    076CC5DC : Critical section address.
    01D0191C : Critical section initialization stack trace.
    075D0000 : Memory block address.
    00140000 : Memory block size.


=======================================
This verifier stop is continuable.
After debugging it use `go' to continue.

=======================================

Given that my code does not leak TCriticalSection, how do I prevent Delphi from doing so.

2

2 Answers

13
votes

Indy10 intentionally leaks critical sections upon exit.

IdStack.pas:

finalization
  // Dont Free. If shutdown is from another Init section, it can cause GPF when stack
  // tries to access it. App will kill it off anyways, so just let it leak
  {$IFDEF IDFREEONFINAL}
  FreeAndNil(GStackCriticalSection);
  {$ENDIF}

IdThread.pas:

finalization
  // This call hangs if not all threads have been properly destroyed.
  // But without this, bad threads can often have worse results. Catch 22.
//  TIdThread.WaitAllThreadsTerminated;

  {$IFDEF IDFREEONFINAL}
  //only enable this if you know your code exits thread-clean
  FreeAndNil(GThreadCount);
  {$ENDIF}
  1. Copy those two files from %delphi_home%\source\Indy\Indy10\System and %delphi_home%\source\Indy\Indy10\Core into your project, or include them in search path.
  2. Rebuild with IDFREEONFINAL or remove the IFDEF directives.
0
votes

How do you know your code is not leaking anything unless you have run with ReportMemoryLeaksOnShutdown := True or FastMM4 in FullDebugMode to catch ALL memoryleaks (your code and Delphi libraries)?
Running your app in FullDebugMode would also give you the StackTrace of the unfreed memory allocations.
You will probably find that, indeed, you are leaking the IdStack Critical Section.

You may want to give a look at this CodeRage 2 session: Fighting Memory Leaks for Dummies. It mainly shows how to use FastMM to prevent/detect memory leaks in Delphi. Was for D2007 but still relevant for D2009.