2014-09-30 2 views
1

저는 C++로 약간 장난 꾸러기이며, 그 중 일부는 "재시작 가능"코드를 가지고 있습니다. 재치하려면 :던져진 예외가 C++에서 누설 됨

class handler { 
public: 
    virtual ~handler() {} 
    virtual response handle(request &req) = 0; 
}; 

response dispatch(request &req, handler &hnd) { 
    try { 
     return(hnd.handle(req)); 
    } catch(handler &rep) { 
     return(dispatch(req, rep)); 
    } 
} 

을 그리고, 코드의 다른 부분에 : resp::messagehandler의 서브 클래스

static response serve(request &req) { 
    throw(resp::message("Merdel", {"Test"})); 
} 

합니다.

이 잘 작동하는 것처럼 보이지만 내가 Valgrind의를 실행할 때,이 메모리 누수 나에게 말한다 :

==2609== 352 bytes in 11 blocks are definitely lost in loss record 12 of 16 
==2609== at 0x4C270FE: memalign (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2609== by 0x4010BEF: tls_get_addr_tail (dl-tls.c:529) 
==2609== by 0x401110F: __tls_get_addr (dl-tls.c:767) 
==2609== by 0x668FC9B: __cxa_get_globals (eh_globals.cc:63) 
==2609== by 0x668F5EE: __cxa_allocate_exception (eh_alloc.cc:132) 
==2609== by 0x61DDA5E: serve(arw::request&) (arwtest.ashc:7) 
==2609== by 0x640E18B: arw::funhandler::handle(arw::request&) (arw.cpp:95) 
==2609== by 0x640E1C5: arw::dispatch(arw::request&, arw::handler&) (arw.cpp:100) 
==2609== by 0x640E487: arw::dispatch(ashd::request const&, arw::handler&) (arw.cpp:119) 
==2609== by 0x61DDBA7: _htstart (arwtest.ashc:11) 
==2609== by 0x403CCD: servehtstart (request.c:228) 
==2609== by 0x4040C5: servereq (request.c:303) 

serve(arw::request&) (arwtest.ashc:7) 위에 나열된 serve 기능입니다.

왜 메모리 누수가 발생합니까? C++ 런타임은 이러한 예외를 자동으로 해방해야한다는 것을 알고 있습니다. 어쨌든 수작업으로 수동으로 해제 할 수있는 능력이있는 것은 아닙니다.

나는 유사한 주제에 대해 이전 질문 인 thesetwo을 찾았지만 예외적 인 상황에서 단일 누출 예외 만 처리하므로이 코드는 요청 당 예외가 누출됩니다. 11 개의 개별 블록이 유출되었으며 이는이 테스트 중에이 테스트 기능을 11 번 실행했기 때문입니다.)

편집 : 그것은 관련 여부를인지 잘 모르겠지만, 그것은 역 추적에 servehtstartservereq 순수-C 프로그램의 기능이 있음을 주목할 필요가있을 수 있습니다. _htstart 이상은 dlopen() ed 인 공유 객체의 C++ 코드입니다. 또한이 공유 객체의 dlopen만이 libstdc++을 처리하는 데 관련이 있습니다.

+1

프로그램은 어떻게 끝나나요? – quantdev

+0

@quantdev :이 특정 코드는'servereq'가 반환 된 후에 끝나는 별도의 스레드에서 실행됩니다. 이 예제에서는 이러한 예외 중 하나가 스레드마다 발생합니다. 프로그램은'SIGTERM'을 전송하기 때문에 끝납니다. 실행중인 스레드에서 메인 루프를 잡아 내고 종료합니다. 또한 질문 편집을 참조하십시오. – Dolda2000

+1

정리되지 않은 스레드 로컬 저장소입니다. 아마 괜찮을거야. –

답변

2

이것은 glibc의 특정 버전에서 현재 Debian Stable (2.13)에있는 버전을 포함하지만 버그가 수정 된 버그입니다. 데비안 테스팅 설정 (glibc 2.19 사용)에서 동일한 프로그램을 실행하면 메모리 누수가 발생하지 않습니다.

분명히 glibc 2.13은 dlopen() 개체에 의해 도입 된 스레드 로컬 메모리를 올바르게 정리하지 않습니다. libstdc++dlopen()의 결과로로드되기 때문에 여기에서 발생합니다. 이 문제는 이전에이 두 버그 보고서에 설명되어 있습니다 :

glibc는이 문제가 e6c61494이었다 고정하는 커밋합니다.

감사합니다. @quantdev, @DavidSchwartz. 귀하의 의견은 내가 무엇을 찾아야 할지를 깨닫게했습니다.