如何防止堆栈损坏?

5

我正在尝试调试Android本地应用程序中的段错误。 GDB显示如下:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 5200]
0xbfcc6744 in ?? ()
(gdb) bt
#0  0xbfcc6744 in ?? ()
#1  0x5cfb5458 in WWMath::unProject (x=2.1136094475592566, y=472.2994384765625, z=0, mvpMatrix=@0x0, 
    viewport=@0x0, result=@0x0) at jni/src/core/util/WWMath.cpp:118
#2  0x00000000 in ?? ()

能否获取良好的堆栈?或找到堆栈被破坏的地方?

更新: 提到的函数采用引用:

bool WWMath::unProject(double x, double y, double z, const Matrix &mvpMatrix,
         const Rect& viewport, Vec4& result)

同时将简单的本地变量引用作为最后一个参数传递:

Vec4 far, near;
if (!unProject(x, y, 0, tMvp, viewport, near))

3
你是否使用了-g-O0或者-O1进行编译? - James M
1
...并且始终使用所有可能的警告进行编译。至少要使用“-W -Wall -Wextra -pedantic”。 - Kerrek SB
不需要使用“-W”,它只是“-Wextra”的旧名称。http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wextra-259 - BoBTFish
@JamesMcLaughlin -g -O0@KerrekSB 我已经开启了所有警告,只有“未使用参数”和有符号/无符号操作。-pedantic会导致构建崩溃,我们的项目非常庞大,有时代码很混乱。 - Equidamoid
3个回答

5
我们没有太多信息可供参考!除了小心处理寻址外,没有通用规则可以避免内存损坏。

但是在我看来,您溢出了一个float数组,因为虚假地址0xbfcc6744equates到合理的float-1.597,这与GDB报告的其他值相一致。

覆盖返回地址导致执行跳转到该值,因此请特别查看函数WWMath::unProject的调用者,其本地变量位于其返回地址之前,以查找有问题的缓冲区。 (现在我们已经找到了,是near。)


太好了!这是旋转矩阵的值。 - Equidamoid

2
使用--fstack-protector-all编译程序,如果函数返回时破坏了栈并且这种破坏包括返回地址周围的栈区域,则程序将中止(使用信号SIGABRT)。
Stack-protector-all不是一个很好的调试工具,但它很容易尝试,并且有时确实可以捕获此类问题。虽然它不会指向导致问题的哪一行,但至少可以缩小到单个函数。一旦您获得了该信息,就可以在GDB中逐步执行以确定有问题的行。

0
只通过从可疑代码的开头逐行步进,并寻找栈被破坏的时刻来解决了这个问题。(它是使用二维数组进行的丑陋指针算术。)
而似乎有另一种方法:尝试将所有东西放入堆中,并希望不正确的操作会导致段错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接