c++ - 我是否能够确定在我部署了一个程序后发生了什么,我写了一个数组的末尾?

标签 c++ arrays arduino esp8266 arduino-esp8266

<分区>

我编写了一个程序,将一个浮点值写入数组末尾之后的一个位置。我有代码和编译后的二进制文件。我是否能够以某种方式确定我是否幸运并且该程序将永远有效?

我们正在谈论的程序是针对 ESP8266 的。

最佳答案

为了查明您的情况发生了什么,您必须查明您可能错误访问的内存位置到底是什么。

有两件事我预计会发生:您覆盖了您不应该覆盖的数据,或者您写入了一个以某种方式受到保护的内存位置并产生了意外中断(我不确定 ESP32 是否支持内存保护以及您是否使用它)。

我希望你的二进制文件有调试信息,否则这将是更多的工作。如果你有一个相当高质量的调试器,你应该能够继续。 Objectdump(假设您使用 GNU 工具链)也有帮助。

首先,您需要一个函数可能访问的所有数组的列表。如果它是在函数中直接引用的局部或静态变量,这很容易。如果数组在指针中传递给您的函数,您需要追溯它以找到可以传递给您的函数的所有数组。 对于您的函数可能访问的每个数组,您必须进行以下分析:

数组分配在哪里?是静态变量、栈变量还是分配在堆上?

静态分配的数组

在这种情况下数组的地址是常量,您可以通过查阅二进制文件的符号表找到它的地址。

您可以使用 objdump --syms 并查看数组的位置(或使用调试器)。然后你试着找出下一个符号。这是将被覆盖的变量。 如果在下一个地址没有找到变量,请检查该地址是否超过了芯片内部存储器的末尾或进入了另一段(可能是堆栈)。

堆栈数组

对于这些,您将必须找出堆栈上分配的内容。 在调试器中列出局部变量并查看地址,如果一个就在你的数组后面,你就知道什么被覆盖了。 否则请阅读您的编译器使用的调用约定和/或查看程序集以找出被覆盖的数据会发生什么。 可能是一些未命名的临时文件位于错误写入的位置。

据我所知,ESP32 上的堆栈会向下增长,因此如果数组是堆栈帧中的最后一个变量,您将覆盖分配函数调用者堆栈帧中的第一个变量(除非由于对齐而保留了一些空间)。您可能可以在调试器中检查它。 从我在 Xtensa 手册中读到的,堆栈指针和返回地址应该在寄存器中传递。

堆数组

对于这些,您必须了解您正在使用的 malloc 实现。 如果幸运的话,数组的大小会四舍五入到某种对齐方式。否则,您可能会覆盖其他堆数据或 malloc 用来管理堆的一些内存。两者都肯定需要修复错误,因为您很难预测会发生什么。

结构或其他数组中的数组

无论这些分配在哪里,数组后可能还有结构的其他成员,因此您可以预测当这些被覆盖时会发生什么。由于对齐,也可能存在填充(检查 sizeof(YourStruct))。如果该数组是数组数组的一部分而不是最后一个,您可能会覆盖后续数组的第一个条目。

我不确定这是否涵盖您的情况,但我希望它能为您分析问题提供一个起点。无论如何,您可能会达到进一步分析比发布错误修复成本更高的程度。

关于c++ - 我是否能够确定在我部署了一个程序后发生了什么,我写了一个数组的末尾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45101523/

相关文章:

c++ - 在 C++ 中读取每行 2 个数字

c++ - 如何更改键盘行为?

c - 使用Arduino生成黄金码调制的正弦波

c++ - 在C中进入循环一次

c++ - _read 函数返回文件句柄的过时值

c++ - 你能把库放在命名空间里吗?

python - 从 1 维数据 reshape 生成 4 维数组

c++ - Arduino 字符数组到整数值

php - 如果未设置 key , $_GET ['key' ] 会返回什么?

python - 大型二维 numpy 数组中相同元素的高效成对计算