Clang link-time optimization with replaced operator new reasons do not match free () / delete in valgrind

When using clang 3.5.0 with -flto and connecting to a shared library, it seems that the operator delete calls in the shared library do not correspond to the same character resolution order as the operator new calls from the main objects, Example:

shared.cpp

 void deleteIt(int* ptr) { delete ptr; } 

main.cpp

 #include <cstdlib> #include <new> void* operator new(size_t size) { void* result = std::malloc(size); if (result == nullptr) { throw std::bad_alloc(); } return result; } void operator delete(void* ptr) noexcept { std::free(ptr); } void deleteIt(int* ptr); int main() { deleteIt(new int); return 0; } 

This is what happens when I create it and run it through valgrind:

 $ clang++ -std=c++11 -g -O3 -flto -fuse-ld=gold -fPIC -shared shared.cpp -o libshared.so $ clang++ -std=c++11 -g -O3 -flto -fuse-ld=gold main.cpp -L. -lshared -o main $ LD_LIBRARY_PATH=. valgrind --quiet ./main ==20557== Mismatched free() / delete / delete [] ==20557== at 0x4C2B6D0: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==20557== by 0x4009F7: main (main.cpp:19) ==20557== Address 0x5a03040 is 0 bytes inside a block of size 4 alloc'd ==20557== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==20557== by 0x4009EA: operator new (main.cpp:5) ==20557== by 0x4009EA: main (main.cpp:19) ==20557== 

You can see that it finds valgrind operator delete , but uses operator new from main.cpp . In contrast, the same build with gcc (just replace clang++ with g++ ) is fine. Any ideas why, or how to get around this?

EDIT: Import and export symbol for @Deduplicator.

 $ objdump -T main | c++filt | grep operator 0000000000400990 g DF .text 0000000000000033 Base operator new(unsigned long) 0000000000000000 DF *UND* 0000000000000000 Base operator delete(void*) $ objdump -T libshared.so | c++filt | grep operator 0000000000000000 DF *UND* 0000000000000000 GLIBCXX_3.4 operator delete(void*) 
+5
c ++ clang valgrind lto
source share
1 answer

Looking at the dump object , it is obvious that operator delete(void*) not exported main .

 $ objdump -T main | c++filt | grep operator 0000000000400990 g DF .text 0000000000000033 Base operator new(unsigned long) 0000000000000000 DF *UND* 0000000000000000 Base operator delete(void*) 

Look that the section in which operator delete(void*) is stored is *UND* : it is not!

Now that the obvious rejection of the clang part can make a good error report, since we already have a minimal test case.

Now, how to get clang to store and export operator delete(void*) as strip help?
The answer looks at possible attributes , there is a good one:

is used
This attribute bound to a function means that the code must be emitted for the function, even if it seems that the function is not referenced. This is useful, for example, when a function refers only to an inline assembly. When applied to a member function of a C ++ class template, the attribute also means that the function is created if the class instance is created.

Put this in the code:

 void operator delete(void* ptr) noexcept __attribute__((used)) { 

And to fight, clang no longer abuses him.

+5
source share

All Articles