Wednesday, June 4, 2008

Standard delete v's Firebird delete

Alex and I have just committed a slew of changes to the code in Firebird 2.1.
This all started when we did the 32 bit builds for Firebird on MacOSX.

We found that in remote we would get asserts trying to create a database. On deeper and further investigation over a period of a couple of weeks we realised that in some cases the standard delete was being called instead of the redefined version in Firebird i.e. it invoked free() instead of
MemoryPool::globalFree(). After some extensive googling we found other people have also run into similar problems.

As a solution it was suggested to use:
1. Use switches -fvisibility=hidden and -fvisibility-inlines-hidden together.
2. Use switch -fvisibility=hidden and __attribute__((always_inline)).

Trying with second combination we found that we sometimes got (depending on the version of gcc) an error:
sorry, unimplemented: inlining failed in call to 'void operator delete(void*) throw ()'.

It seems that without -fvisibility=hidden and __attribute__((always_inline)) gcc is
using non-inline body for operator delete. And is randomly using the wrong body, the one from the standard
operator delete.

The first combination helps to avoid this bug - but any entrypoint, which is to be exported, now has to be marked with __attribute__((visibility="default")).

1 comment:

Laurie said...

I haven't tested this exact scenario, but would the use of the visibility pragma (push, pop) around prototypes for the exported functions (i.e. create one header file containing prototypes for the exported functions and include it wherever such functions are defined) resolve this more cleanly than the __attribute__ qualifier?

I suspect that such use of #pragma visibility is impractical with member functions; I'd never export (mangled) C++ symbols anyway.

Just an idea.