更改从未到达的行时发生堆栈溢出 - 为什么以及如何防止它?

Stack overflow happening when changing a line which is never reached - why and how to prevent it?

我正在使用 Zephyr 在嵌入式环境中开发一些东西。

本质上,我正在处理由堆栈溢出引起的引导循环。当我更改 main 中函数调用的 unused 参数时,堆栈溢出消失了。为了确保问题不在函数内部,我将其实现硬编码为 return 0;.

像这样的违规行创建了一个引导循环:

uint8_t port;
ret = foo(&port, NULL, NULL);

但是缺少取消引用端口的行通常有代码 运行:

uint8_t port;
ret = foo(NULL, NULL, NULL);

请注意,正如我已经说过的,foo 的实现被硬编码为 return 0。这些参数根本没有被使用过。此外,我确信这条线在 运行 时间(在本例中)从未真正到达,因为它存在于一些需要我的交互实际通过的条件之后。

我已经开始放弃并将事情归咎于内存故障或 ESD 损坏,但是当我在备用硬件上尝试使用相同的代码进行相同的更改时,我发现同样的事情发生了。我错过了什么?我真的不知道我还能做些什么来找出发生这种情况的原因以及如何解决它。我无法访问此微控制器 (SAMD21) 的调试器,所以我有点不知所措...有什么想法(或至少表示同情)吗?

当您删除该参数时 运行 没有任何错误还是有其他错误?如果您在程序的某处写入错误的内存(例如,分配的内存大小为零),则更改程序代码的不相关部分,例如更改结构的大小或函数的参数,可以更改发生致命错误的位置以及致命错误的类型。

没关系,我找到了罪魁祸首 - 一个简单的堆栈溢出。在将 uint8_t port 变量声明添加到 main 之前,我离它只有一个字节。 foo() 中未用作参数的变量已被编译器优化掉。在调用堆栈上少一个字节显然足以防止溢出。

解决方案:增加堆栈大小并小心不要让不必要的物品堵塞它。