【发布时间】:2020-05-08 16:04:41
【问题描述】:
我正在使用 Zephyr 在嵌入式环境中开发一些东西。
基本上我正在处理由堆栈溢出引起的引导循环。当我在 main 内部更改函数调用的 unused 参数时,堆栈溢出消失了。为了确保问题不在函数内部,我将其实现硬编码为return 0;。
这样的违规行会创建一个引导循环:
uint8_t port;
ret = foo(&port, NULL, NULL);
但是缺少取消引用端口的那行代码运行正常:
uint8_t port;
ret = foo(NULL, NULL, NULL);
请注意,正如我已经说过的,foo 的实现被硬编码为返回 0。参数在任何时候都没有使用。此外,我确信在运行时(在这种情况下)实际上永远不会到达这条线,因为它存在于一些需要我的交互实际通过的条件之后。
我已经开始放弃并将事情归咎于内存故障或 ESD 损坏,但是当我在备用硬件上尝试相同的代码并进行相同的更改时,同样的事情发生了。我错过了什么?我真的不知道我还能做些什么来找出为什么会发生这种情况以及如何解决它。我无法访问此微控制器 (SAMD21) 的调试器,所以我有点不知所措……有什么想法(或至少同情)吗?
【问题讨论】:
-
您是否尝试查看汇编代码?由于某种原因,编译器可能生成了完全不同的代码。
-
查看汇编程序,在堆栈上放置一个哨兵,看看您离溢出有多近,并仔细查看您的映射文件以确保一切都符合您在内存中的想法。如果事情真的非常接近溢出,那么减少大小或重组内存。
-
你可以在运行时检查标记值,仔细使用 printf() :)
-
@MichaelDorgan 在这种情况下它不起作用,因为引导循环会阻止 printf() 甚至执行!
-
通常未定义的行为,尤其是堆栈溢出,往往会导致当您更改不相关的代码行时,您会暴露或隐藏问题。但这并不意味着特定线路是违规者,问题可能在任何地方。在像 SAMD 这样的现代 M0+ + 一个不错的调试器上,应该可以在堆栈底部设置一个写断点,然后你会确切地看到代码出错的地方,包括指令跟踪。这意味着您将在 20 分钟而不是 1 周内解决错误。
标签: c pointers embedded stack-overflow