[fpc-pascal] How can a project determine if it's using cmem?
Michael Van Canneyt
michael at freepascal.org
Mon Jul 9 10:56:53 CEST 2012
On Mon, 9 Jul 2012, Mark Morgan Lloyd wrote:
> Mark Morgan Lloyd wrote:
>> Tomas Hajny wrote:
>>> On Wed, July 4, 2012 11:32, Mark Morgan Lloyd wrote:
>>>> When building a shared library, I'm putting a (function that returns a)
>>>> magic number into both the library and the calling program. This returns
>>>> an integer, and allows the program and library to check their exposed
>>>> APIs without risk.
>>>> How can code in the library test whether it is using cmem, so that it
>>>> can tell the caller that it's safe to call functions that move strings
>>>> and objects around? It's obviously trivial to rely on a compile-time
>>>> conditional, but can this be done in a way that doesn't rely on this?
>>> First of all, you can easily check whether the default memory manager is
>>> used by calling IsMemoryManagerSet. Obviously, this doesn't tell whether
>>> the custom memory manager is cmem or something else (e.g. TraceManager
>>> from HeapTrace). However, you could possibly try to check the distance
>>> between the individual MemoryManager methods retrieved using
>>> GetMemoryManager - while that is not bulletproof by any means, it provides
>>> at least some indication.
>>> Finally, if there are certain major changes to features provided by
>>> individual memory managers (like some operation being safe or not), adding
>>> some TMemoryManager method allowing to provide this information may be the
>>> best solution for the future.
>> Thanks Tomas (and Ludo). Under the circumstances I think IsMemoryManagerSet
>> is probably an adequate solution, since the real risk is that somebody
>> messes about with the start of the main unit (or with the project settings)
>> without appreciating that the cmem import is crucial to operation elsewhere
>> in the program (or, analogously, that a shared library will crash when some
>> functions are called).
>> Having something- e.g. an exported string- in cmem would be a partial
>> solution, but would have to be checked in the main unit. With any solution,
>> I think that testing that cmem was the first import could be a challenge.
> I've added a feature request as
> http://mantis.freepascal.org/view.php?id=22386 but am being told "First of
> all, you are wrong in thinking that using Cmem is a prerequisite to being
> able to use longstrings etc. as parameters and results..."
> Obviously I accept that there might be other suitable memory managers, but
> cmem is the one normally referred to. Far be it from me to argue with those
> more experienced than I, but the suggestion I'm trying to make is that it
> would be desirable if each module (i.e. every shared library plus the main
> program) could confirm that it's in a state where it can share e.g.
> longstrings, objects etc. with others. In common usage, that implies that
> cmem is not only imported, but is imported /first/.
Ignoring for a second that other possibilities exist:
If the interface of your DLL requires the use of cmem, it is the programmer's
duty to ensure that cmem is used.
I don't even see why you would want to check it, since your interface definition
implies it. In that case, not using cmem is simply not an option, and if the
programmer does not include it properly, it's his fault:
in that case he provided a faulty DLL.
He could equally well be exporting a function with a correct name, but a wrong
set of parameters. You can't check that either and it probably would not occur
to you to do so in the first place...
To me, your cmem unit problem falls in the same category, and consequently
I do not think a solution in the RTL is needed.
More information about the fpc-pascal