I have a mixed C/C++ program. It contains a flex/bison parser which targets C, while the remainder is C++.
Being C, the generated parser and scanner manage their memory with malloc, realloc and free. They are good enough to expose hooks allowing me to submit my own implementations of these functions. As you might expect, the rest of the (C++) program “wants” to use new, delete, etc.
Doing a little research seems to show that the relevant standards do not guarantee that such mixing should work. Particularly the C “heap” is not necessarily the C++ “free area”. It seems the two schemes can trample each other.
On top of this, someday (soon) this program will probably want to integrate a customized heap implementation such as tcmalloc, used by both C and C++.
What is the “right” thing to do here?
Given the desire to integrate tcmalloc (which explains how to link with C programs) I’m tempted to find some cross-type, cross-thread, cross-everything overload/hook/whatever into C++ memory management. With that I could point all C++ allocation/release calls back to their C equivalents (which in turn land on tcmalloc.)
Does such a pan-galactic global C++ hook exist? Might it already be doing what I want, similar to how ios_base::sync_with_stdio secretly marries iostream and stdio by default?
I am not interested in talking about stdio vs. iostreams, nor about switching parser generators nor using the C++ flex/bison skeletons (they introduce independent headaches.)
EDIT: Please include the names of those sections of the C++ standard that support your answer.
The standard does guarantee that mixing the two allocation variants will work. What it doesn’t permit is things like calling
freeon memory that came fromnew, since they may use a totally different arena for the two types.Providing you remember to call the correct deallocation function for a given block of memory, you will be fine. They won’t trample each other if you follow the rules and, if you don’t follow the rules then, technically, you’re doing the trampling, not them 🙂
The controlling part of the C++11 standard is
20.6.13 C librarywhich states, paraphrased:calloc,malloc,freeandreallocare provided, based on the C standard.::operator new()or::operator delete().That second bullet point is interesting in light of what you’re eventually proposing, dropping in
tcmallocto replace the C heritage functions and have C++ use it as well.There’s a footnote in the standard which explains why they don’t use let
malloc()call::operator new():However, while it allows
operator new()to callmalloc(), I’m not sure that the standard actually requires it. So, to be safe, you’d probably want to injecttcmallocinto both the C and C++ areas.You’ve indicated you already know how to do that for C. For C++, it can be done by simply providing the entire set of global
operator new()/delete()functions in your code, suitably written to calltcmallocunder the covers. The C++ standard states in3.7.4 Dynamic storage duration: