更好的 GDB 应对调用堆栈溢出的可用性
GDB 能否检测到通常在无限递归错误中的调用堆栈溢出,并打印一些不错的错误和上下文消息,而不是下面给出的代码,这对新手来说很难理解,对我们所有人来说都很不方便。在这种情况下,如果 GDB 能够通过检查所涉及的(成员)函数或变量指针中的重复模式来检测哪些对象(指针)参与了无限递归循环,那将是超级酷 。我在 Ubuntu 上使用 gdb-7.3-dev。输出如下:
Program received signal SIGSEGV, Segmentation fault.
0x008577e9 in _int_malloc (av=0x9483c0, bytes=4) at malloc.c:4249
4249 malloc.c: Filen eller katalogen finns inte.
in malloc.c
(gdb) up
#1 0x00859f53 in __libc_malloc (bytes=4) at malloc.c:3660
3660 in malloc.c
(gdb)
#2 0x00788b87 in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
(gdb)
#3 0x0809cb7e in __gnu_cxx::new_allocator<Ob*>::allocate (this=0xbf80025c, __n=1)
at /usr/include/c++/4.6/ext/new_allocator.h:92
92 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
(gdb)
#4 0x0809c7c8 in std::_Vector_base<Ob*, std::allocator<Ob*> >::_M_allocate (
this=0xbf80025c, __n=1) at /usr/include/c++/4.6/bits/stl_vector.h:150
150 { return __n != 0 ? _M_impl.allocate(__n) : 0; }
(gdb)
#5 0x0809c931 in std::vector<Ob*, std::allocator<Ob*> >::_M_insert_aux<Ob*> (
this=0xbf80025c, __position=Cannot access memory at address 0x0
) at /usr/include/c++/4.6/bits/vector.tcc:324
324 pointer __new_start(this->_M_allocate(__len));
(gdb) up
#6 0x0809c65a in std::vector<Ob*, std::allocator<Ob*> >::emplace_back<Ob*> (
this=0xbf80025c, __args#0=@0xbf800190) at /usr/include/c++/4.6/bits/vector.tcc:102
102 _M_insert_aux(end(), std::forward<_Args>(__args)...);
(gdb)
#7 0x0809c5c4 in std::vector<Ob*, std::allocator<Ob*> >::push_back (this=0xbf80025c,
__x=@0xbf800190) at /usr/include/c++/4.6/bits/stl_vector.h:840
840 { emplace_back(std::move(__x)); }
(gdb)
/Per
Can GDB detect call stack overflows typically in infinite recursion bugs and print some nice error and context message instead of the code given below which is very hard to understand for novices and very inconvenient for all of us. In this case it would be super-cool if GDB could detect which objects (pointers) that were involved in the infinite recursion loop by checking repetitive patterns in the (member-) function- or variable-pointers involved. I'm using gdb-7.3-dev on Ubuntu. Output follows:
Program received signal SIGSEGV, Segmentation fault.
0x008577e9 in _int_malloc (av=0x9483c0, bytes=4) at malloc.c:4249
4249 malloc.c: Filen eller katalogen finns inte.
in malloc.c
(gdb) up
#1 0x00859f53 in __libc_malloc (bytes=4) at malloc.c:3660
3660 in malloc.c
(gdb)
#2 0x00788b87 in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
(gdb)
#3 0x0809cb7e in __gnu_cxx::new_allocator<Ob*>::allocate (this=0xbf80025c, __n=1)
at /usr/include/c++/4.6/ext/new_allocator.h:92
92 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
(gdb)
#4 0x0809c7c8 in std::_Vector_base<Ob*, std::allocator<Ob*> >::_M_allocate (
this=0xbf80025c, __n=1) at /usr/include/c++/4.6/bits/stl_vector.h:150
150 { return __n != 0 ? _M_impl.allocate(__n) : 0; }
(gdb)
#5 0x0809c931 in std::vector<Ob*, std::allocator<Ob*> >::_M_insert_aux<Ob*> (
this=0xbf80025c, __position=Cannot access memory at address 0x0
) at /usr/include/c++/4.6/bits/vector.tcc:324
324 pointer __new_start(this->_M_allocate(__len));
(gdb) up
#6 0x0809c65a in std::vector<Ob*, std::allocator<Ob*> >::emplace_back<Ob*> (
this=0xbf80025c, __args#0=@0xbf800190) at /usr/include/c++/4.6/bits/vector.tcc:102
102 _M_insert_aux(end(), std::forward<_Args>(__args)...);
(gdb)
#7 0x0809c5c4 in std::vector<Ob*, std::allocator<Ob*> >::push_back (this=0xbf80025c,
__x=@0xbf800190) at /usr/include/c++/4.6/bits/stl_vector.h:840
840 { emplace_back(std::move(__x)); }
(gdb)
/Per
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Gdb 无法真正做到这一点,因为堆栈溢出检测通常由编译器实现。编译器实现这一点的一般方式是使用金丝雀。金丝雀是堆栈上的一个值(位置位于局部变量和堆栈帧之间),检查它是否被覆盖。堆栈溢出的问题在于,您最终会得到损坏的堆栈,并且调用堆栈通常没有用处。解决这个问题的方法是使用 br 命令在 canary 位置设置一个观察点。所以当金丝雀被覆盖时它就会崩溃
Gdb cannot really do this as the stack overflow detection is generally implemented by the compiler. The general way compilers implement this is with canaries. The canary is a value on the stack (the location is between the local variables and the stack frame) that is checked if it got overwritten. The problem with stack overflows is that you end with a damaged stack and the call stack is often not useful. A way around this is to set a watchpoint on the canary location with the br command. So it will break right at the point when the canary is getting overwritten