[fpc-pascal] DLL calling Firebird 2: crashes at the end

Mark Morgan Lloyd markMLl.fpc-pascal at telemetry.co.uk
Sun Sep 28 13:02:45 CEST 2014

Reinier Olislagers wrote:

> May be me, but I have trouble understanding why:
> 1. A regular program loading Firebird .so/.dlls works without any
> specified cmem etc. Here application<>Firebird dll
> 2. An FPC library, coded similarly to 1., fails.
> Here application<>dll<>Firebir dll
> The difference between the 2 seems to me application coupled directly to
> FB dll versus coupling to FPC dll.
> Why should that make a difference?
> Why should I worry about memory managers etc in the second case but not
> the first? (Assuming I did not create problems with application<>dll
> parameter passing)

Everything below is my understanding. I'm happy to be corrected.

I've not used the Firebird interface libraries directly to any great 
extent (only the PostgreSQL ones), but the thing that occurs to me is 
that when the database library allocates memory for e.g. a resultset of 
indeterminate size it is subsequently responsible for freeing it. This 
is akin to OS (as distinct from application) programming, where the 
caller of an OS function probably has limited access rights to the 
memory containing structures that the OS returns, and definitely 
shouldn't assume that it's got arbitrary allocate/free rights to it.

So in your case (2) there are three separate binaries which potentially 
allocate and free memory: (i) the database library (ii) the custom 
DLL/so and (iii) the application program, and in the general case each 
one should free precisely those areas of memory that it allocated: not a 
block more and preferably not a block less.

Now if we assume that the database library has its own competent memory 
manager, and that its callers correctly tell it to free memory as soon 
as they're done with it (e.g. once a resultset has been parsed); that 
leaves potential problems in the custom library and application code.

If the custom library never made any attempt to access Pascal-type 
(long) strings, dynamic arrays, or anything else on the heap which might 
be reallocated or extended when referenced (i.e. not just at creation), 
then you'd not need to do anything special. But as soon as the custom 
library tries to e.g. change the length of a string or dynamic array it 
makes a call to the memory manager, and if it's not sharing the same 
memory manager as the main app used to allocate the string/array that's 
a recipe for disaster.

Now it might, potentially, be possible to tell a DLL/so as it is being 
loaded to link itself to the heap manager built into the main app. But 
the current preferred way is for the library and the app to use the same 
external memory manager, which is where importing cmem comes in.

So if you're getting crashes and your parameters are right, the first 
thing to check is that your custom library and the main app are both 
importing and using cmem before anything else such as HeapTrc. My 
experience is that that works, and if it isn't working then time you put 
into fixing it will probably be a useful investment.

Here endeth the lesson. Go in peace.

Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

More information about the fpc-pascal mailing list