STM32嵌入式存储器overflow/leak检测

STM32 embedded memory overflow/leak detection

我被咬了几次屁股,我会写一个超出范围的数组。我已经在一个特定的固件上工作了 2 年多,并且怀疑现在几乎不可能找到溢出 - 例如:

uint8_t example[50];
uint8_t example2[100];
for(uint8_t i = 0; i < sizeof(example2); i++)
   example[i] = i;

我明白上面的代码示例是原始的。这只是我要描述的示例。

是否有可用的包或函数可以检测这些“泄漏”?

带有标志 -Wall 的最新版本的 GCC 将检测简单的错误,例如您示例中的问题,并打印警告。

工具 Valgrind 更高级,但也需要更多工作才能正确配置和使用。

宇宙中没有一种工具可以检测出所有可能的错误,所以从最容易使用的开始。

静态分析只能做这么多,但这里有一些我每天都在使用的工具:

  • cppcheck
  • clang-tidy(LLVM 的一部分)- 如果您不使用 CMake,设置起来并不容易。

此外,正如 Tom V 指出的那样,打开尽可能多的警告(-Wall 是最小值 - here 是一组很好的警告标志起始集)。

GCC 警告 out-of-bound 此类问题。使用 -Wall -pedantic -O1:

编译此代码示例
int main(void) {
    int example[50];
    for (int i = 0; i < 100; i++)
        example[i] = i;
    return example[0];
}

...导致此编译警告(使用 ARM GCC 11.2 (linux),可在 Godbolt 上测试,正如 Tom V 的回答中已经指出的那样:

<source>: In function 'main':
<source>:4:20: warning: iteration 50 invokes undefined behavior [-Waggressive-loop-optimizations]
    4 |         example[i] = i;
      |         ~~~~~~~~~~~^~~
<source>:3:23: note: within this loop
    3 |     for (int i = 0; i < 100; i++)
      |                     ~~^~~~~
Compiler returned: 0

在这种情况下,需要优化选项标志 -O1(或 -O2-Os)才能从 GCC 获取未定义的行为警告。 -O3优化了loop out,所以不会有警告。没有优化(默认选项 -O0)也不会导致警告,因为据我所知,GCC 显然只在优化循环时注意到 out-of-bound 问题(参见 -Waggressive-loop-optimizations)。

(一些注意事项: GCC 的 -fstack-check-fstack-protector 选项也值得一看(运行时检查)。 Valgrind 或其他 static/dynamic 分析工具也很有用。然而,在微控制器上,在运行时在目标上分析程序通常不是那么容易,模拟器或在开发机器上用不同的编译器编译程序的 non-platform 特定部分也有帮助,使它更僵硬。

相关主题已在此处讨论:Accessing an array out of bounds gives no error, why?, How does the gcc option -fstack-check exactly work?)

工具 Frama-c ,通过 Eva 插件,允许进行值分析:它能够计算每个变量的每个可能值,然后检测(除其他问题外)数组溢出,即使在非平凡的代码中也是如此来源。