简体   繁体   中英

C++ operator new overloading, compilation error

When I overload new operator globally to track mem leaks, I get compilation error in the following place

 ::new(__tmp) _Rb_tree_node<_Val>;

looks like they allocate and fill the node there. Following is the error:

/home/symbol/Android/Sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include/functional: In static member function 'static void std::_Function_base::_Base_manager<_Functor>::_M_clone(std::_Any_data&, const std::_Any_data&, std::true_type)':/home/symbol/Android/Sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include/functional:1870:9: error: '__dest' does not name a type
new (__dest._M_access()) _Functor(__source._M_access<_Functor>());

Below is my overloading code:

void* operator new(std::size_t sz,char const* file, int line){  
return newImpl(sz,file,line);
}

void* operator new [](std::size_t sz,char const* file, int line){  
return newImpl(sz,file,line);
}

void operator delete(void* ptr) noexcept{
auto ind=std::distance(myAlloc.begin(),std::find(myAlloc.begin(),myAlloc.end(),ptr)    );
myAlloc[ind]= nullptr;
free(ptr);
}

#define new new(__FILE__, __LINE__)
#define new new(__FILE__, __LINE__)

that is illegal. Under the standard, the behavior of a program with a keyword #define d to something else is unspecified. Your program is ill-formed, no diangostic required.

If you are wondering why you are breaking this particular time, it is because the C++ standard library uses placement new itself where it passes a void pointer to be constructed into.

Your code takes the naked new that starts a placement new expression, and replaces it with a different placement new exprssion. Which then makes the rest of the code nonsense, as we get:

new("some file", 1234) (some void pointer) some_type( constructor_args... )

which is utterly illegal syntax.

If you want to catch 99% of allocations, retool your code to use a different allocator when creating std containers. Sweep your code to replace non-placement new with something you can legally #define to something different (like TRACED_NEW and TRACED_NEW_PLACEMENT for placement new).

Use these in your allocator.

One way to replace all uses of std::container s with ones that use your allocators is to write your own notstd namespace with template-aliases that replace the allocator (or whatever other retooling you want to do). This custom allocator can then use your TRACED_NEW_PLACEMENT or TRACED_NEW .

And the result is a well defined program instead of a hack that, at best, currently works with your current compiler.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM