我是否能够确定在我编写一个程序之后发生了什么?我写了一个数组的末尾?

时间:2017-07-14 11:10:03

标签: c++ arrays arduino esp8266 arduino-esp8266

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

我们所谈论的节目是针对ESP8266的。

1 个答案:

答案 0 :(得分:1)

为了找出您的情况会发生什么,您必须找出您可能错误访问的内存位置。

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

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

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

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

静态分配的数组

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

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

堆叠数组

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

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

堆数组

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

结构或其他数组中的数组

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

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