valgrind 未检测到的 malloc_consolidate (malloc.c) 中的分段错误

我的程序出现分段错误,我找不到原因.最糟糕的是,有问题的函数并不总是导致段错误.

My program goes in segmentation faults, and I cannot find the cause. The worst part is, the function in question does not always lead to segfault.

GDB 确认错误并产生此回溯:

GDB confirms the bug and yields this backtrace:

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

Address 类的GetS 方法将数字(uint32_t m_address)转换为字符串并返回.代码(很简单)如下:

Method GetS of class Address translates a number (uint32_t m_address) into a string and returns it. The code (very simple) is the following:

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

此外,从回溯中可以看出,m_address 已正确定义.

Besides, as can be seen in the backtrace, m_address is properly defined.

现在,我尝试使用 valgrind 运行我的程序.程序没有崩溃,可能是因为 valgrind 在其他函数中替换了 malloc ().

Now, I have tried to run my program using valgrind. The program doesn't crash, likely due to the fact that valgrind replaces malloc () among other functions.

错误摘要显示没有内存泄漏:

The error summary shows no memory leaking:

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

所有可能丢失引用回溯如下:

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)

我认为这与错误无关.但是,可以在 以下链接/a>.

I don't think this is related to the bug. However, the code in question can be found following this link.

我正在考虑 libstdc++ 中的一个错误.然而,这种可能性有多大?我也升级了这样的图书馆.这是我系统上当前安装的版本.

I am thinking of a bug in libstdc++. However, how likely would that be? I have also upgraded such library. Here's the versions currently installed on my system.

$ 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++ 使用哪个版本,以及是否有一些方法可以强制使用特定版本.

Now the thing is, I am not sure which version g++ uses, and whether there's some means to enforce the use of a particular version.

我在琢磨的是修改GetS.但这是我知道的唯一方法.你有什么替代方案吗?

What I am pondering is to modify GetS. But this is the only method I know. Do you suggest any alternative?

最终,我什至考虑将 std::string 替换为更简单的 char*.也许有点激烈,但我不会把它放在一边.

Eventually, I am even considering to replace std::string with simpler char*. Maybe a little drastic, but I wouldn't set it aside.

有什么优点吗?

提前谢谢大家.

最好,吉尔

推荐答案

好的.这不是问题:

我正在考虑 libstdc++ 中的一个错误

I am thinking of a bug in libstdc++

问题是您覆盖了一些内存缓冲区并损坏了内存管理器使用的结构之一.困难的部分将是找到它.valgrind 不会为您提供有关在分配的内存结束后写入的信息.

The problem is that you overwrote some memory buffer and corrupted one of the structures used by the memory manager. The hard part is going to be finding it. Does not valgrind give you information about writting past the end of an allocated piece of memory.

不要这样做:

最后,我什至考虑用更简单的 char* 替换 std::string.也许有点激烈,但我不会把它放在一边.

Eventually, I am even considering to replace std::string with simpler char*. Maybe a little drastic, but I wouldn't set it aside.

内存管理问题已经够多了.这只会增加更多的问题.std::string 或内存管理例程绝对有 NOTHING 错误.它们经过大量测试和使用.如果出了什么问题,全世界的人都会开始尖叫(这将是个大新闻).

You already have enough problems with memory management. This will just add more problems. There is absolutely NOTHING wrong with std::string or the memory management routines. They are heavily tested and used. If there was something wrong people all over the world would start screaming (it would be big news).

http://mercurial.intuxication.org/hg/lte_sim/file/c2ef6e0b6d41/src/ 阅读您的代码,您似乎仍然停留在 C 风格的编写代码中(<代码>带有类的C).所以你有 C++ 的力量来自动化(你的代码爆炸),但仍然有与 C 相关的所有问题.

Reading your code at http://mercurial.intuxication.org/hg/lte_sim/file/c2ef6e0b6d41/src/ it seems like you are still stuck in a C style of writting code (C with Classes). So you have the power of C++ to automate (the blowing up of your code) but still have all the problems associated with C.

您需要根据所有权重新审视您的代码.你通过指针传递的东西太多了.因此,很难跟踪指针的所有权(以及谁负责删除它).

You need to re-look at your code in terms of ownership. You pass things around by pointer way too much. As a result it is hard to follow the ownership of the pointer (and thus who is responsible for deleting it).

我认为找到错误的最佳方法是为每个类编写单元测试.然后通过 val-grind 运行单元测试.我知道这很痛苦(但你应该从一开始就这样做,现在你一下子就感受到了痛苦).

I think you best bet at finding the bug is to write unit tests for each class. Then run the unit tests through val-grind. I know its a pain (but you should have done it to start with now you have the pain all in one go).

相关文章