If this line: ClientCommunication.Free;
is causing an exception.
There are a few things you can do here.
FreeAndNil
Replace calls to AObject.free
with calls to freeandnil(AObject)
.
If you just do the free, the old pointer will still have a non-nil reference and Assigned(AObject)
will not be able to tell a freed and active object apart.
Beware of clones
Another mistake you may make is that you've cloned the object like so:
Object1:= TObject1.Create;
//.... lots of code
Object2:= Object1;
//.... lots of code
FreeAndNil(Object2); <<-- freeing the clone-reference is a mistake
//.... lots of code
Object1.Free; <<-- exception: it's already freed
FastMM4 options
Download the latest FastMM4 from http://sourceforge.net/projects/fastmm/
It has a few extra bells and whistles from the one included with Delphi.(*)
Among those whistles is an extra diagnostic mode that makes your program dead slow, but also catches out a lot of those heap corruption bugs you seem to be suffering from.
Open up defines.inc
and change this:
{$ifdef DEBUG}
{.$define EnableMemoryLeakReporting}
{.$define FullDebugMode}
{.$define RawStackTraces}
{$endif DEBUG}
Into this
{$ifdef DEBUG}
{$define EnableMemoryLeakReporting}
{$define FullDebugMode}
{$define RawStackTraces}
{$define CatchUseOfFreedInterfaces} <<-- very useful
{$define LogMemoryLeakDetailToFile}
{$define LogErrorsToFile}
{$define CheckHeapForCorruption} <<-- :-)
{$endif}
There's a nice article here: http://wiert.me/2009/07/29/delphi-fastmm-using-fastmm4-for-debugging-your-memory-allocations-part-1-introduction/
If you don't feel like mucking about with the inc file, there a little utility that will do it for you at: http://jedqc.blogspot.com/2007/07/new-fastmm4-options-interface.html
(*) I think the Delphi one has most of the debug stuff as well, but not 100% sure. Regardless can't hurt to get the latest (greatest) version.
Or buffer overflow
If your ClientCommunication
object has some internal structure free will do extra work.
Imagine the following code:
TUnrelatedObject = class
buffer: array[0..99] of integer;
procedure DoWork;
end;
TUnrelatedObject.DoWork;
var
i: integer;
begin
for i:= 0 to 100 do buffer[i]:= maxint; <<-- buffer overrun
end;
Imagine that ClientCommunication
is right next to UnrelatedObject
in the heap.
The call to DoWork
will overwrite data of ClientCommunication
as well.
This may or may not trigger an access violation in DoWork. If it doesn't then the error will be very hard to trace, because it will show up in a different and totally unrelated places.
Enable range checking {$R+}
in your application.
Warning
Remember to not ship the debug version to your clients.
With all the debugging your program will be dead slow.