- 1、本文档共5页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
控制堆栈大小作者NiclasLindblom,IARSystems你是否曾遇到过因
控制堆栈大小作者 Niclas Lindblom, IAR Systems你是否曾遇到过因堆栈溢出而导致的奇怪错误?你是否需要在很小的存储器系统上运行应用程序?那么你应该知道堆栈必须足够大但不是太大。传统方法是根据一定猜测和经验来解决这个问题,或者跟踪每个函数以及它所需的空间。另一个检查堆栈是否溢出的方法是在最顶层的存储器单元中使用一个预定的模式,并在代码运行结束后检查其是否被写入。曾经是这样?是的,现在你可以让IAR Embedded Workbench 使用堆栈调试插件来做这些冗长乏味的工作吧。它是怎样运行的?插件使用一个预定的模式,它被预先写入分配为堆栈的存储器中,0xCD。另外,它会跟踪所有使用堆栈的事物。
当要调试你的代码时,只需打开 View 菜单并选择 Stack 命令。
现在,你在 IAR Embedded Workbench 中得到一个新的窗口,Stack窗口。
要配置堆栈调试,请在 Stack 窗口中右键单击,选择Option。IDE Option 窗口会展示出之前选择的堆栈选项。
在这里你需要选择何种等级的堆栈使用会令你紧张不安。预先选择的是 90%。选择当超出堆栈阈值时发出警告(Warn when exceeding stack threshold)和当堆栈指针出界时发出警告(Warn when stack pointer is out of bounds)。
?
现在可以运行应用程序了。用这样的方法来运行程序:确保代码的执行中使用最多的堆栈,然后中断执行。查看 Stack 窗口。现在你可以看到当前的堆栈情况和保存的数据。让你的鼠标指针停留在 Stack 窗口上方的灰绿色栏上。
在我的例子中,只使用了 1024 个字节中的 288个字节,因此这里有可能减少堆栈的尺寸。可以在与此工程文件相对应的连接命令文件中作这些设置,本例中是LPC2378__Flash.xcl。
我需要编辑的命令行是:
-D_CSTACK_SIZE=400
?
既然我知道这个应用程序只使用了288个字节,我决定给它再增加另外的 10%,总共是 320,或者说是0x140。记住连接器命令文件中的地址是用16进制写的,但没有 0x 的前缀。
-D_CSTACK_SIZE=140 // Changed from 400
?
我保存文件并重新编译应用程序。当我检查实际使用的堆栈情况时,我发现刚好在安全线上:仅使用了 80%。假如我不能保证我在测试执行程序中已经达到了可用的最大值,我可能还需要相应地增加安全边界。
?
要找出所用堆栈的确切值,你需要确定能以这样一种方式来运行应用程序:堆栈的使用最大化。而这会导致这样一个问题:是什么使用了堆栈?基本来说,它是函数,这意味着嵌套函数使用的堆栈更多。在函数中,令堆栈的使用最多的常常是局部变量和参数。一个使用很多大型局部变量的函数所用的堆栈会比许多不使用局部变量的嵌套函数所使用的堆栈还要多。?
另一个堆栈调试插件的特点是能看到堆栈中具体是什么。很容易用一个例子来说明。我中断程序然后进行单步调试,直到我得到这个画面。
这里你可以看到堆栈最顶层是被函数 GLCD_SendCmd 中的两个 1 字节的局部变量所使用。
?
你能够使用堆栈调试插件来找出使用堆栈的函数。在一个可疑点设置一个断点,检查堆栈、单步调试然后检查。在我的例子中,我在我认为可能使用了最多堆栈的函数前设置了断点,然后单步调试代码。
在这个例子中,是库函数 printf 使用了最多的堆栈空间。
值得注意的是,堆栈调试插件不会影响性能,除了它在调试后将数据转换到 IAR Embedded Workbench 所用的时间。从给出命令如 Step 到获得结果所需要的延迟依赖于数据量。
这里提到的方法--分配堆栈后写入预设模式,然后确定它是否被写入--不是很简单。你能够自己分配存储器,但要防止它没有被初始化。如果它是堆栈的最后一项的话,它可能无法被插件检测到。如果你向插件所使用的堆栈(0xCD)中写入相同的数据,这种方法会失效。
文档评论(0)