我正在写一个函数来弄清楚一个给定的线性不等式系统是否有一个解决方案,突然间它在看似无害的变化后开始给出错误的答案.
我解除了一些变化,重新做了它们,然后在接下来的两个小时内进行了调整,直到我把它减少到荒谬.
以下内容,插入到函数体的任何位置,但程序中没有其他地方,修复它:
if(0) { __asm__("nop\n"); __asm__("nop\n"); __asm__("nop\n"); __asm__("nop\n"); }
这是一个学校作业,所以我可能不应该在网上发布这个功能,但这太荒谬了,我认为没有任何背景可以帮助你.所有功能都是一堆数学和循环.它甚至没有触及未在堆栈上分配的内存.
请帮我理解这个世界!我不喜欢将它归结为GCC,因为调试的第一条规则并不是责怪编译器.但是,哎呀,我即将到来.我在G5塔上运行Mac OS 10.5,并且有问题的编译器将自己标识为'powerpc-apple-darwin9-gcc-4.0.1',但我认为它可能是冒名顶替者......
更新:Curiouser和curiouser ...我用nops和没有来扩展.s文件.不仅要检查太多差异,而且没有nops,.s文件是196,620字节,并且有156,719字节.(!)
更新2:哇,应该已经发布了代码!我今天带着新鲜的眼睛回到了代码,并立即看到了错误.看下面我的怯懦自我回答.
大多数情况下,当你修改代码并且它修复你的问题时,它就是某种类型的内存损坏问题.我们可能需要查看实际的代码才能进行正确的分析,但根据可用的信息,这将是我的第一个猜测.
它是错误的指针算法,直接(通过指针)或间接(通过超过数组的末尾).检查所有阵列.如果您的阵列是,请不要忘记
int a[4];
然后a [4]不存在.
你正在做的是意外地覆盖堆栈中的东西.堆栈包含本地,参数和函数的返回地址.您可能会以额外的noops治愈的方式损坏返回地址.
例如,如果你有一些代码在返回地址中添加一些内容,那么插入那些额外的16字节的noops就可以解决问题,因为你不会返回到下一行代码,而是返回到一些noops的中间.
例如,一种向返回地址添加内容的方法是通过本地数组或参数的末尾
int a[4]; a[4]++;
几天忙于其他事情后,我回到了这里,立刻想出来了.对不起,我没有尽快发布代码,但很难找出显示问题的最小示例.
根本问题是我在递归函数中遗漏了return语句.我有:
bool function() { /* lots of code */ function() }
什么时候应该是:
bool function() { /* lots of code */ return function() }
这是有效的,因为通过优化的魔力,正确的价值碰巧在正确的时间出现在正确的寄存器中,并使其到达正确的位置.
这个bug最初是在我将第一次调用打入其自己的特殊功能时引入的.而且,在那一点上,额外的nops是第一种情况直接内联到一般递归函数之间的区别.
然后,由于我不完全理解的原因,内联第一个案例导致正确的值在正确的时间不在正确的位置,并且函数返回垃圾.