【发布时间】:2010-12-17 21:31:01
【问题描述】:
在多线程嵌入式软件(用 C 或 C++ 编写)中,必须为线程提供足够的堆栈空间,以允许它完成其操作而不会溢出。在某些实时嵌入式环境中,堆栈的正确大小至关重要,因为(至少在我使用过的某些系统中),操作系统不会为您检测到这一点。
通常,新线程(除了主线程)的堆栈大小是在创建线程时指定的(即在 pthread_create() 等的参数中)。通常,这些堆栈大小被硬编码为在最初编写或测试代码时已知良好的值。
但是,未来对代码的更改通常会破坏硬编码堆栈大小所基于的假设,并且有一天,您的线程进入其调用图的较深分支之一并溢出堆栈 - 导致整个系统或默默地破坏内存。
我个人在线程中执行的代码在堆栈上声明结构实例的情况下看到了这个问题。当结构被扩充以容纳额外的数据时,堆栈大小会相应地膨胀,可能会导致堆栈溢出。我想这对于已建立的代码库来说可能是一个巨大的问题,因为无法立即知道将字段添加到结构的全部效果(线程/函数太多,无法找到使用该结构的所有位置)。
由于对“堆栈大小”问题的通常回答是“它们不可移植”,因此我们假设编译器、操作系统和处理器都是本次调查的已知数量。我们还假设不使用递归,因此我们不处理“无限递归”场景的可能性。
有哪些可靠的方法可以估计线程所需的堆栈大小?我更喜欢离线(静态分析)和自动的方法,但欢迎所有想法。
【问题讨论】:
-
作为这个领域的新手,我不得不问:最有可能的第一步不是消除使用结构作为自动变量吗?无论指针指向的结构做了多少,指针的大小都不会改变。并且显式请求内存(而不是假设堆栈空间可用)将允许代码处理内存不可用的情况。
-
或者更好的是,堆栈上的结构应该只存储指向动态分配内存的指针。这样您就可以两全其美:自动生命周期管理,因为它在堆栈上,并且所有占用超过几个字节的内容都可以堆分配以节省堆栈空间。
-
@mcl:在 C++ 中,您可以使用 scoped_ptr,但在 C 中,您将拥有动态内存管理,这无济于事。我确实同意应避免使用堆栈容器(数组),因此在 C++ STL 容器中有所帮助。
-
@mcl 在嵌入式软件中,显式请求(动态)内存(例如 malloc)会带来一系列问题,例如长时间运行时的堆碎片。在大多数情况下,任何此类分配内存的失败都将是产品的不可接受的失败,而不是可以有效地“由代码处理”的失败。但是仍然可以考虑静态分配内存而不是堆栈。但在许多系统中,就整体内存使用而言,从堆栈变量更改为静态变量实际上可能会让您落后。
标签: c++ c embedded stack static-analysis