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 me
Ok. Dug up an old working draft of the standard (2/28/2011 rev 3242.) It appears the relevant sections are 3.7.4 Dynamic storage duration
and 18.6.1 Storage allocation and deallocation
.
In short it seems the pan-galactic hook I wanted are the global new and delete operators themselves. If one respects some semantics (in 3.7.4.1
and 3.7.4.2
: basically delegate to new_handler
as needed) one is allowed to replace
void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);
to arrest default memory management of the entire C++ program. I still can't find the section that proves @paxdiablo right, but I'm willing to run with it for now.
The standard does guarantee that mixing the two allocation variants will work. What it doesn't permit is things like calling free
on memory that came from new
, 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 library
which states, paraphrased:
calloc
, malloc
, free
and realloc
are 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 tcmalloc
to 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()
:
The intent is to have operator new() implementable by calling std::malloc() or std::calloc(). In other words, they want to avoid a circular dependency.
However, while it allows operator new()
to call malloc()
, I'm not sure that the standard actually requires it. So, to be safe, you'd probably want to inject tcmalloc
into 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 call tcmalloc
under the covers. The C++ standard states in 3.7.4 Dynamic storage duration
:
The library provides default definitions for the global allocation and deallocation functions. Some global allocation and deallocation functions are replaceable.
A C++ program shall provide at most one definition of a replaceable allocation or deallocation function. Any such function definition replaces the default version provided in the library.
The following allocation and deallocation functions are implicitly declared in global scope in each translation unit of a program:
void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);
You don't have to worry about any memory allocated by the generated code of Flex or Bison; they take care of it themselves. For the rest, just use new
and delete
. (And Flex and Bison are capable of generating C++, of a sort. In general, I've found running the output through a simple script, using sed
has been sufficient to make their output truly C++ compatible.)