Bei Verwendung von Clang 3.5.0 mit -flto und Verknüpfung mit einer gemeinsam genutzten Bibliothek scheint es, dass Aufrufe an operator delete
in der gemeinsam genutzten Bibliothek nicht Folgen Sie der gleichen Reihenfolge der Symbolauflösung wie Aufrufe an operator new
von den Hauptobjekten. Beispiel:Clang Link-Zeit-Optimierung mit ersetzten Operator neue Ursachen mismatched frei()/löschen in Valgrind
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;
}
Hier ist, was passiert, wenn ich es bauen und führen Sie es durch 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==
Sie können sehen dass es die operator delete
des Valgrind findet, aber unter Verwendung operator new
von main.cpp
. Im Gegensatz dazu funktioniert der gleiche Build mit gcc (ersetzen Sie einfach clang++
mit g++
) gut. Irgendwelche Ideen warum oder wie man es umgehen kann?
EDIT: Symbol importiert und exportiert, wie von @Deduplicator angefordert.
$ 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*)
Haben Sie tatsächlich durch den Code getreten (ich erwarte irgendwie, dass die Shared Library einen eigenen Heap hat, also bin ich nicht ganz überrascht) –
Ich denke, der Operator-delete-line für Haupt zeigt das Problem an. Aus irgendeinem Grund exportiert main nicht delete ... Tatsächlich wurde delete gelöscht. – Deduplicator
Guter Fang. Interessanterweise, wenn ich die C++ 14-Überladung von 'operator delete' hinzufüge und' -std = C++ 14' verwende, wird diese exportiert und alles funktioniert.Aber 'operator delete (void *)' wird immer noch nicht exportiert. –