[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