章节列表

堆栈使用量测量

2018-01-12 09:42:05 +0000 李述铜

在学习任务的切换原理课时中,我们了解到需要为什么配备单独的栈空间用于存储任务的运行状态。同时我们也知道,栈空间也用于局部变量,函数调用时传递的参数。通常情况下,栈的空间是有限的,所以我们要采取方式对使用量进行测量,避免栈溢出破坏其它任务数据或内核数r。

本课时就是要介绍这样一种测试机制。

主要内容

测量原理非常简单,如下图所示。

用更形象的说法来表示,可以这样看:

  • 首先我们将栈的整个空间“打扫干净”,即初始化为0;
  • 任务运行时,任务对栈的使用总是从某个起始位置向某个方向前进或回退,而不是随意使用任意单元。
  • 测量时,我们只需要从另一端开始检查,检查干净的区域有多大(即值为0的单元数),这个大小就是未使用的堆栈大小,然后用整个空间大小减去,即可得使用大小。

这种方法有一定局限,可能难以测出准确的使用量,注意事项如下:

这里针对图中几点补充说明:

  • 准确的说:运行时间长并不那么重要,关键是要想办法让所有的代码尽可能的都执行一遍。这样就能让所有需要使用堆栈的情况都出现,从而使得获得最大堆栈使用量成为可能。这在某些情况下无法实现,例如你的应用中调用了第三方库,而这个库对你是闭源的,你很难得知库内的代码是否都执行;
  • 即使出现所有代码都运行一遍,也可能出现测量值与实际值差异较大的情况。例如,执行了相同的代码,不同的条件下,其占用的堆栈量却不同,以下面代码为例:

    { char buffer[256]; for (i = 0; i < num; i++) { buffer[i] = i; } } 对于这段代码,假设编译器生成的代码中,除了在堆栈中分配256B外,后面的代码执行全部使用寄存器完成,没有再分配堆栈空间。那么,无论是num=1,还是num=256,上面的所有代码都执行了一遍,但是后者实际使用的堆栈空间却比前者多255。这是因为char buffer[256]虽然分配了256B堆栈单元,但此时没有使用,仍然是干净的。在num=1时,仅仅对第1个单元进行了改写,将该单元“弄脏”,其余单元未使用。而后者则全部使用。在测量堆栈时,如果你只测量了Num=1的情况,那么测量值就比真实值少了255。

综上所述:使用该测量方法能否得准确值,取决于你有没有办法让所有的堆栈使用情况都出现。这个要求可能很难,所以一般可以考虑尽可能根据系统需求让所有功能都跑一遍,测量出使用值后,再多预留一部分空间(比如1/4,具体由你自己决定)。

重点难点

注意事项

如果你有更好的测量方法,欢迎分享给我!

常见问题