Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 检测堆栈覆盖错误_C_Debugging_Arm_Cortex M3 - Fatal编程技术网

C 检测堆栈覆盖错误

C 检测堆栈覆盖错误,c,debugging,arm,cortex-m3,C,Debugging,Arm,Cortex M3,我正在为Cortex-M3嵌入式微控制器Atmel SAM3S开发一个软件 我正在使用IAR EWARM IDE和编译器。 我怀疑由于某种原因,我有一个缓冲区溢出,或内存泄漏,这会导致堆栈损坏,因为我突然发现自己卡在了代码空间之外 我问这个问题的原因是,很难找出到底是什么导致了这场混乱,我想知道当你想找出问题的原因时,你使用了哪些技术 您是否使用内存调试器、电路内跟踪调试硬件等。程序计数器是一个寄存器,因此它不能被覆盖。正如您所说,可能发生的情况是,堆栈被覆盖,然后执行一条返回指令,从堆栈中读取

我正在为Cortex-M3嵌入式微控制器Atmel SAM3S开发一个软件 我正在使用IAR EWARM IDE和编译器。 我怀疑由于某种原因,我有一个缓冲区溢出,或内存泄漏,这会导致堆栈损坏,因为我突然发现自己卡在了代码空间之外

我问这个问题的原因是,很难找出到底是什么导致了这场混乱,我想知道当你想找出问题的原因时,你使用了哪些技术


您是否使用内存调试器、电路内跟踪调试硬件等。

程序计数器是一个寄存器,因此它不能被覆盖。正如您所说,可能发生的情况是,堆栈被覆盖,然后执行一条返回指令,从堆栈中读取无效的返回地址,从而导致跳转到la-land

我最喜欢的调试方法是打印出来,当然,这在嵌入式目标上可能很困难。第二个最好的方法是逐步完成可疑程序


您还应该调查导致跳转的已知因素,例如中断服务例程。

程序计数器是一个寄存器,因此它不能被覆盖。正如您所说,可能发生的情况是,堆栈被覆盖,然后执行一条返回指令,从堆栈中读取无效的返回地址,从而导致跳转到la-land

我最喜欢的调试方法是打印出来,当然,这在嵌入式目标上可能很困难。第二个最好的方法是逐步完成可疑程序


您还应该调查导致跳转的已知因素,例如中断服务例程。

您应该尝试使用加那利值。基本上是这样的-假设您有一些结构:

将其修改为如下所示:

struct foo {
    unsigned long canary1;
    unsigned long bar;
    void * baz;
    unsigned long canary2;
};
初始化结构时,将一些任意值放入canary1和canary2。每当您在结构上执行某些操作时,请检查这些值是否保持不变。这样,如果您有缓冲区溢出或堆栈崩溃,您将检测到它。您可以对自动变量执行相同的内部函数:

int foo(int bar) {
      unsigned long canary1 = 0xDEADBABE;
      char baz[20];
      unsigned long canary2 = 0xBAD0C0DE;
      ...
}
等等。在返回之前,不要忘记检查值是否保持不变。此外,如果您可以让代码一致地跳转到相同的位置,那么可以尝试将一些代码放在那里或断点,并获得堆栈跟踪


GCC知道如何自己添加这些金丝雀值,但我不知道您的编译器是否能够做到这一点。但是您仍然可以手动执行。

您应该尝试使用金丝雀值。基本上是这样的-假设您有一些结构:

将其修改为如下所示:

struct foo {
    unsigned long canary1;
    unsigned long bar;
    void * baz;
    unsigned long canary2;
};
初始化结构时,将一些任意值放入canary1和canary2。每当您在结构上执行某些操作时,请检查这些值是否保持不变。这样,如果您有缓冲区溢出或堆栈崩溃,您将检测到它。您可以对自动变量执行相同的内部函数:

int foo(int bar) {
      unsigned long canary1 = 0xDEADBABE;
      char baz[20];
      unsigned long canary2 = 0xBAD0C0DE;
      ...
}
等等。在返回之前,不要忘记检查值是否保持不变。此外,如果您可以让代码一致地跳转到相同的位置,那么可以尝试将一些代码放在那里或断点,并获得堆栈跟踪


GCC知道如何自己添加这些金丝雀值,但我不知道您的编译器是否能够做到这一点。但是您仍然可以手动操作。

我在STM32上使用IAR EWARM时遇到类似问题。内存转储、反汇编、金丝雀,都没有结果。最后回到早期版本的EWARM,问题就消失了。我给IAR的支持部门发了一条信息,但从未得到回复。对不起,我不记得这是哪个版本的EWARM。那是几年前的事了


我会打开一个记忆窗口,先试试金丝雀测试。如果它仍然随机跳出代码空间,请尝试安装较旧版本的EWARM。

我在STM32上使用IAR EWARM时遇到类似问题。内存转储、反汇编、金丝雀,都没有结果。最后回到早期版本的EWARM,问题就消失了。我给IAR的支持部门发了一条信息,但从未得到回复。对不起,我不记得这是哪个版本的EWARM。那是几年前的事了


我会打开一个记忆窗口,先试试金丝雀测试。如果它仍然随机跳出代码空间,请尝试安装较旧版本的EWARM。

我可以补充的一点是,对于ARM芯片,可能是某个地方存在BL而不是BX或BLX导致芯片进入错误的Thumb/ARM模式。与后来的芯片不一样,但仍然

当我发现无处跳转时,我会查找坏的函数指针表、任何中断向量表的覆盖,以及最容易测试的堆栈溢出。将已知字节值放入堆栈区域,当崩溃发生时,查看调试器剩余的堆栈数量。如果没有,那就去吧

我也会做标准的看看什么是变化
在过去的X天里,我试着隔离所有问题。最后,只需将代码打印出来,尝试缩小坏跳转发生的范围。如果你能把它归结为一个或两个函数,你可以跟踪汇编程序,看看它是编译器问题,内存问题,还是中断问题。祝你好运

我可以补充的一点是,对于ARM芯片,可能是某个地方有BL而不是BX或BLX导致芯片进入错误的Thumb/ARM模式。与后来的芯片不一样,但仍然

当我发现无处跳转时,我会查找坏的函数指针表、任何中断向量表的覆盖,以及最容易测试的堆栈溢出。将已知字节值放入堆栈区域,当崩溃发生时,查看调试器剩余的堆栈数量。如果没有,那就去吧


我也会做一些标准的事情,看看在过去的X天里发生了什么变化,来尝试隔离任何问题。最后,只需将代码打印出来,尝试缩小坏跳转发生的范围。如果你能把它归结为一个或两个函数,你可以跟踪汇编程序,看看它是编译器问题,内存问题,还是中断问题。祝你好运

我们做了类似的事情,在数据的末尾放置一个主金丝雀值,然后bss堆栈从末尾向后增长。我们在启动时初始化该值,并在堆栈溢出或随机写入时不断检查它。我们做类似的事情,在数据末尾放置一个主金丝雀值,然后bss堆栈从末尾向后增长。我们在启动时初始化该值,并在堆栈溢出或随机写入时不断检查它。