我在尝试调试似乎是一些非常奇怪的行为时遇到了一些问题。例如,我们有:
static const char* LOG_FORMAT = "0x%02x,%.5f,";
并且指针变化没有明显的原因。有时是垃圾,有时是代码中其他地方定义的其他常量字符串(或部分)。我们偶尔也会看到代码跳转到不应该运行的不同部分(状态变量似乎在没有被要求的情况下改变)。有2或3种常见故障模式,它们似乎是随机发生的。它是一个相对较大的代码库,添加或删除某些部分会更改失败行为(或完全删除它),即使这些部分从未被引用过。
目前最好的理论是它是一个与记忆相关的问题,因为我们已经通过细齿梳更新了所有最近的变化,并且插入代码段以移动物体的简单行为似乎发生了变化或删除行为。
调试此问题或类似问题的最佳方法是什么?发现调试器有时很有用,而不是其他人(但可能是用户错误)。
补充说明。 ARM7,使用KeilμVision4和armcc v4.1编译器。
答案 0 :(得分:1)
这意味着程序中某处存在指针错误/内存损坏......这可能是由许多不同的事情引起的。
最简单的方法是运行程序直到main的开始,然后添加"写"断点到变量。这应该直接指出有问题的代码。
一个可能的原因是堆栈溢出,其中堆栈被放置在错误的内存位置,因此在溢出时它会开始覆盖.data
或.bss
。见this article。
您可以通过在启动时将所有堆栈内存设置为已知值(例如0xAA)来调试堆栈溢出,让程序运行一段时间,尝试将其暴露给尽可能多的用例,然后中断并检查堆栈的内存,以查看仍然保留已知值的深度。如果这接近堆栈的末尾,则很可能会发生堆栈溢出。
答案 1 :(得分:0)
这看起来像是堆栈错位问题。您的堆栈可能在单字(四字节)边界上对齐,而不是双字(八字节)边界。
这就是为什么删除和添加不相关的部分会导致不同的行为。堆栈从对齐到未对齐,取决于它之前的数据量。
损坏的格式说明符是另一条线索。在调用可变参数函数之前,未对齐的堆栈通常不会引起任何问题 - 尤其是传递需要双字对齐的值的函数。
要调试它,您应该在调用printf
(或使用格式说明符的任何函数)时设置断点,并查看堆栈指针。如果SP未在8字节边界上对齐,则表明您已找到问题。