2014-09-18 3 views
5

-flto와 함께 3.5.0을 사용하고 공유 라이브러리와 링크 할 때 공유 라이브러리에서 operator delete을 호출하면 주 개체에서 operator new에 대한 호출과 동일한 기호 확인 순서를 따르십시오.대체 된 연산자를 사용한 Clang 링크 시간 최적화가 valgrind에서 free()/delete가 일치하지 않음

$ 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== 
: 예 :

shared.cpp :

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

MAIN.CPP : 나는 그것을 구축하고 Valgrind의를 통해 실행할 때

#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; 
} 

여기에 발생하는 상황

valgrind의 operator delete을 찾고 있지만 operator newmain.cpp입니다. 반대로 gcc (정확하게 clang++g++으로 대체)와 동일한 빌드가 올바르게 작동합니다. 왜 어떤 아이디어, 또는 어떻게 해결할 수 있습니까?

EDIT : @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*) 
+0

실제로 코드를 밟았습니까 (공유 라이브러리가 자신의 힙을 가지기를 기대하므로 완전히 놀랍지는 않습니다) –

+0

main에 대한 operator-delete-line은 문제를 나타냅니다. 어떤 이유로, main은 delete를 export하지 않습니다 ... 사실 삭제는 제거되었습니다. – Deduplicator

+0

잘 잡습니다. 흥미롭게도,'operator delete '의 C++ 14 오버로드를 추가하고'-std = C++ 14'를 사용하면 그 중 하나가 내보내지고 모든 것이 작동합니다.그러나'operator delete (void *)'는 여전히 export되지 않습니다. –

답변

5

object-dump 보면, operator delete(void*)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*) 

operator delete(void*)가 저장되는 부분은 *UND* 것을 참조 : 그것은 거기!

우리가 이미 최소의 테스트 케이스를 가지고 있기 때문에, clang의 부분에 명백한 실패가 있습니다. 좋은 버그 리포트를 만들 수 있습니다.

이제는 clang이 반창고로 보관하고 내보내는 방법은 무엇입니까? ,

함수에 연결
이 속성을 사용하는 코드는 함수가 참조하지 않은 것 같습니다 경우에도 기능에 방출해야 의미
대답은 looking at the possible attributes이며,이 좋은 하나 . 예를 들어 함수가 인라인 어셈블리에서만 참조되는 경우에 유용합니다. C++ 클래스 템플릿의 멤버 함수에 적용될 때이 특성은 클래스 자체가 인스턴스화되는 경우 함수가 인스턴스화된다는 것을 의미합니다.

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

을 봐라, 그 소리는 더 이상 잘못을 프 i :

코드에서 그 퍼팅 없습니다.

+0

버그 보고서 : http://llvm.org/bugs/show_bug.cgi?id=21001 –