Alvaro Herrera wrote:
Craig Ringer wrote:
That said, PostgreSQL does appear to use its own allocator for memory
passed across library boundaries, and if it doesn't pass any FILE
pointers across library boundaries either then that's the worst two
problems that arise with a C runtime mismatch taken care of. As far as I
know, anyway, and I've had the misfortune to have to dig into it a bit.
Note that our allocator uses malloc() underneath.
Sure. That's fine, so long as the wrapper functions palloc and pfree are
real functions that reside in the same DLL on windows. You can pass
pointers around freely, otherwise you couldn't do much at all ... the
problem is with a call path like this:
- DLL2 calls a function in DLL1
- DLL1 malloc()'s some memory and returns a pointer to it
- DLL2 free()'s the pointer
My understanding of the reason that this breaks if DLL1 and DLL2 are
linked to different C runtimes is that it's essentially a double free
plus a memory leak. The allocator in DLL2 has never allocated the memory
so the free call is freeing unallocated memory. It's never properly
freed by the allocator in DLL2, so it's leaked as far as that allocator
is concerned. It's quite possible that my understanding of the problem
isn't correct, though.
In any case, the safe thing to do is:
- DLL2 calls a function in DLL1
- DLL1 malloc()'s some memory and returns a pointer to it
- DLL2 calls a free() wrapper function defined in DLL1
- The free() wrapper in DLL1 calls the real free() to release the memory
If palloc() and pfree() are real functions defined in the same DLL, then
it should be just fine as use of them will ensure that everything uses
the same underlying memory allocator. A problem might arise if Pg ever
passes memory not allocated with palloc() around, though.
It looks like palloc is a macro for the real function
MemoryContextAlloc, and pfree is just a real function - so it should be
fine. They don't expose references to malloc() and free() directly.
This actually applies to any situation in which multiple malloc()/free()
implementations are used - but most people and platforms are sane enough
to avoid that.
And I would think
that we do pass FILE pointers around too; AllocateFile works with FILE,
so any library that's using that method to get to files would be in
trouble (which they should, because it's the way to ensure we don't leak
files on transaction abort and also to ensure that the system continues
to work on the face of lots of open files).
Yep, I'm pretty sure that'll cause issues when using a mingw-compiled
object in a msvc++-compiled copy of Pg.
--
Craig Ringer