我最近因为在嵌入式系统上超越堆而被咬了几次。
这通常是由于写入在堆上声明的数组超过数组的大小,这必须超出其他堆声明的变量,然后导致非常不确定的行为 - 使根本原因难以追踪。
是否有任何方法可以检测/防止嵌入式系统上的这类堆溢出错误?我正在为STM32平台开发,但很高兴知道任何一般方法。我很高兴听到在运行时发现溢出的方法或在编译之前可以发现溢出的静态分析方法。
请注意,因为这是在嵌入式系统上运行的代码,所以malloc
的使用很少 - 大多数堆变量是静态或全局声明的,而不使用malloc
。
答案 0 :(得分:2)
我一直在问你的问题,直到你到达最后一段,似乎对你称之为“堆”的东西感到困惑。所以我假设大多数问题都是在访问数组边界外的内存时发生的,无论数组的内存实际驻留在哪里。
这是我通常尝试做的事情:
现在,这是更多的工作,当然,考虑到这些想法,开始项目肯定会有所帮助。但是多年来我发现在我可以带来更好的工具而不是尝试改进嵌入式环境本身的环境中尝试运行嵌入式代码更容易。
答案 1 :(得分:0)
Malloc可以溢出堆使用,即使不使用也可能导致内存碎片,但是您的测试代码应该能够检测出内存不足错误。通过引用传递的递归函数调用可以溢出堆栈使用。如果使用设定值初始化整个堆栈/堆,则可以扫描它们以查看测试期间使用了多少(例如填充0x3F,测试后查看其中有多少已损坏' )。设置测试用例,最大限度地提高使用率,以获得不会溢出的信心。
1)如果内存充足,请扩展堆栈/堆的大小。
2)如果内存紧张,只考虑静态分配,不要使用malloc的库函数。减少函数深度并避免递归。考虑将较大的局部函数变量推送到全局变量。
答案 2 :(得分:0)
我同意不要在微控制器上尽可能使用malloc。尽管每个人都不这么认为,全局变量的大小是固定的,并且在编译时你知道你的用法是什么。局部变量和函数是极其内存有限的平台上的杀手,因此您必须仔细考虑您创建的每个局部变量以及函数的嵌套程度。只要你不进行递归,你就应该能够通过分析确定你的最坏情况函数嵌套路径,然后消耗多少堆栈。全局在编译时是固定的并且是已知的,但是如果太多而且每个函数都没有大量使用,那么它可能是浪费的。本地是动态的,如果你不这样做,你的分析可能会崩溃到.data或.bss,添加代码来检测只是因为你的闪存非常有限而且性能有限。
你可以尝试valgrind方法(通常用堆填充ram的未声明部分并使用已知值监视堆栈以查看堆栈深入到内存中并通过正常函数嵌套修改该ram)但可能不同,使用链接器脚本将缓冲区放在.data / .bss的顶部,其中堆通常会启动,在那里写一组已知的值,有一个中断快速检查以查看顶部值是否更改,崩溃/刻录/保释/如果是无限循环,走遍堆栈看看你如何嵌套你的方式。
或者只是使用很多全局变量而不必担心它。