2011-07-17 2 views
12

내 프로그램이 분할 오류를 일으키고 원인을 찾을 수 없습니다. 최악의 경우 문제의 기능이 항상 segfault로 이어지는 것은 아닙니다.valgrind가 감지하지 못하는 malloc_consolidate (malloc.c)의 세그먼트 오류

GDB 버그를 확인하고이 역 추적 산출 : 클래스 주소의 GetS 문자열로 번호 (uint32_t m_address)를 번역하고 그것을 반환

Program received signal SIGSEGV, Segmentation fault. 
0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169 
5169 malloc.c: No such file or directory. 
    in malloc.c 
(gdb) bt 
#0 0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169 
#1 0xb7da9035 in _int_malloc (av=<value optimized out>, bytes=<value optimized out>) at malloc.c:4373 
#2 0xb7dab4ac in __libc_malloc (bytes=525) at malloc.c:3660 
#3 0xb7f8dc15 in operator new(unsigned int)() from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#4 0xb7f72db5 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&)() 
    from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#5 0xb7f740bf in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_M_clone(std::allocator<char> const&, unsigned int)() 
    from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#6 0xb7f741f1 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::reserve(unsigned int)() from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#7 0xb7f6bfec in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int)() from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#8 0xb7f70e1c in std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, int)() from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#9 0xb7f5b498 in std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<unsigned long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const() from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#10 0xb7f5b753 in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const() from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#11 0xb7f676ac in std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long)() 
    from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#12 0xb7f67833 in std::basic_ostream<char, std::char_traits<char> >::operator<<(unsigned int)() from /usr/lib/i386-linux-gnu/libstdc++.so.6 
#13 0x08049c42 in sim::Address::GetS (this=0xbfffec40) at address.cc:27 
#14 0x0806a499 in sim::UserGenerator::ProcessEvent (this=0x80a1af0, e=...) at user-generator.cc:59 
#15 0x0806694b in sim::Simulator::CommunicateEvent (this=0x809f970, e=...) at simulator.cc:144 
#16 0x0806685d in sim::Simulator::ProcessNextEvent (this=0x809f970) at simulator.cc:133 
#17 0x08065d76 in sim::Simulator::Run (seed=0) at simulator.cc:53 
#18 0x0807ce85 in main (argc=1, argv=0xbffff454) at main.cc:75 
(gdb) f 13 
#13 0x08049c42 in sim::Address::GetS (this=0xbfffec40) at address.cc:27 
27 oss << m_address; 
(gdb) p this->m_address 
$1 = 1 

방법. 역 추적에서 볼 수 있듯이, m_address이 제대로 정의,

std::string 
Address::GetS() const 
{ 
    std::ostringstream oss; 
    oss << m_address; 
    return oss.str(); 
} 

게다가 : 코드 (매우 간단)는 다음과 같다.

이제 valgrind를 사용하여 프로그램을 실행하려고했습니다. 다른 기능 중에서 valgrind가 malloc()을 대체하기 때문에 프로그램이 중단되지 않을 수 있습니다.

LEAK SUMMARY: 
    definitely lost: 0 bytes in 0 blocks 
    indirectly lost: 0 bytes in 0 blocks 
    possibly lost: 4,367 bytes in 196 blocks 
    still reachable: 9,160 bytes in 198 blocks 
     suppressed: 0 bytes in 0 blocks 

모든 possibly lost이 같은 역 추적을 참조하십시오 :이이 버그에 관련된 생각하지 않습니다

80 bytes in 5 blocks are possibly lost in loss record 3 of 26 
    at 0x4024B64: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
    by 0x40DBDB4: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16) 
    by 0x40DE077: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16) 
    by 0x40DE1E5: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16) 
    by 0x806AF62: sim::UserGenerator::CreateUser(unsigned int) (user-generator.cc:152) 

오류 요약에는 메모리 누출을 보여줍니다. 그러나 문제의 코드는 following this link입니다.

나는 libstdc++의 버그를 생각하고 있습니다. 그러나 그 가능성은 얼마나 될까요? 해당 라이브러리도 업그레이드했습니다. 현재 시스템에 설치된 버전은 다음과 같습니다.

$ dpkg -l | grep libstdc 
ii libstdc++5   1:3.3.6-23 The GNU Standard C++ Library v3 
ii libstdc++6   4.6.1-1  GNU Standard C++ Library v3 
ii libstdc++6-4.1-dev 4.1.2-27 The GNU Standard C++ Library v3 (development files) 
ii libstdc++6-4.3-dev 4.3.5-4  The GNU Standard C++ Library v3 (development files) 
ii libstdc++6-4.4-dev 4.4.6-6  GNU Standard C++ Library v3 (development files) 
ii libstdc++6-4.5-dev 4.5.3-3  The GNU Standard C++ Library v3 (development files) 
ii libstdc++6-4.6-dev 4.6.1-1  GNU Standard C++ Library v3 (development files) 

이제 일이 나는 버전 g++ 사용 확실하지 않다, 특정 버전의 사용을 강제하는 몇 가지 방법이 있는지 여부입니다.

내가 숙고하고있는 것은 GetS을 수정하는 것입니다. 그러나 이것이 내가 아는 유일한 방법입니다. 대안을 제안 해 주시겠습니까?

궁극적으로 std::string을 간단하게 char*으로 바꾸는 것을 고려하고 있습니다. 아마도 조금 과감한 것이지만 나는 그것을 옆으로 두지 않을 것입니다.

장점이 있습니까?

감사합니다.

최저

, JIR

+4

우선,'MALLOC_CHECK_' 환경 변수를 3으로 설정하여 실행 해보는 것이 좋습니다. 이렇게하면 관리 구조의 일부를 오버런하게되면 'malloc'이 일찍 중단 될 수 있고, valgrind는이를 인식하지 못하게됩니다 . 나는 또한 당신이 문제를 숨길 수있는 valgrind suppresion 옵션을 가지고 있는지 확인해보기 바란다. – Hasturkun

+2

나는 당신의 코드를 재검토했다 : 다음의 클래스들은'Rule of Three'를 따르지 않는다 :'BaseStation','MobileTerminal' ,'Network','Simulator','UserGenerator' 이중 삭제로 인한 메모리 손상의 원인 일 수 있습니다. –

+0

@Hasturkun : 시도하고 점검 할 것입니다. 유용한 팁! @ 마틴 : 코멘트 주셔서 감사합니다! 나는 그 부분을 검토 할 것이다. – Jir

답변

24

좋아.

내가

하면 libstdC++의 버그 문제를 생각하고 당신이 어떤 메모리 버퍼를 덮어 및 메모리 관리자에 의해 사용되는 구조 중 하나가 손상된 것입니다 :이 문제가 하지입니다. 어려운 부분이 찾아 낼 것입니다. valgrind는 할당 된 메모리 조각의 끝을지나 writting에 대한 정보를 제공하지 않습니다.

이 작업을 수행하지 마십시오

결국, 심지어 * 간단한 문자와 표준 : : 문자열을 대체하는 것을 고려하고있다. 어쩌면 다소 과감 할 지 모르지만 나는 그것을 옆으로 두지 않을 것이다.

이미 메모리 관리에 문제가 있습니다. 이것은 단지 더 많은 문제를 추가 할 것입니다. 대체로 NOTHING이 std :: string 또는 메모리 관리 루틴에 잘못되었습니다. 그들은 무겁게 시험되고 사용됩니다. 뭔가 이상한 것이 있다면 전 세계 사람들이 비명을 지르는 것입니다 (큰 뉴스가 될 것입니다).

코드를 http://mercurial.intuxication.org/hg/lte_sim/file/c2ef6e0b6d41/src/에서 읽으면 여전히 C 스타일의 코드 (C with Classes)가 붙어있는 것처럼 보입니다. 따라서 C++의 자동화 기능 (코드 불어 내기)은 여전히 ​​있지만 C와 관련된 모든 문제가 있습니다.

소유권 측면에서 코드를 다시 살펴 봐야합니다. 포인터 방식으로 물건을 너무 많이지나칩니다. 결과적으로 포인터의 소유권을 따르기가 어렵습니다 (따라서 누가 그것을 삭제할 책임이 있습니다).

나는 각 클래스에 대한 단위 테스트를 작성하는 것이 가장 좋습니다. 그런 다음 val-grind를 통해 단위 테스트를 실행하십시오. 나는 그 고통을 안다. (그러나 당신은 지금부터 시작해야한다.

+0

존재하지 않는다면 어떻게 알 수 있습니까? :) 힌트를 주셔서 감사합니다. 이렇게 더 많은 것을 배울 수있는 이런 의견에 감사드립니다. 나는 그것을 들여다 볼 것이다. 감사! – Jir