You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式程序栈使用率测量问题:填充哑值结果与预期不符

问题描述

我正在测量嵌入式程序的最大栈使用率。通过生成.su文件,估算出最大栈使用率约为35523B。为验证该数值,我采用栈填充哑值的方法:已知估算值约35KB,故定义STACK_SIZE为40KB,在startup.c中调用main前,将STACK_START到STACK_END的栈空间填充为0XDEADBEEF。运行程序后,通过StackCount函数统计栈使用率,但结果与35523B不符,且修改STACK_SIZE为其他值时,结果每次都会变化。

填充栈的代码:

src = STACK_START;
dst = STACK_END;
while(src < dst){  
  *(src++) = 0xDEADBEEF;

统计栈使用率的代码:

uint16_t StackCount(void)
{  
    volatile unsigned long *start, *end;
    start = STACK_START;
    end = STACK_END;
    uint32_t       countBytes = 0;

    while((*start == 0xDEADBEEF && start < end))
    {
        start++;
        countBytes++;                
    }
        
    printf("stack used:%d bytes \n",STACK_SIZE-countBytes);
    printf("remaining stack :%d bytes\n",countBytes);
         
    return c;
}

错误分析与修正方案

1. 栈填充逻辑的核心错误

  • 循环未闭合:原填充代码缺少},会导致编译错误或未定义行为。
  • 栈生长方向搞反:多数嵌入式CPU的栈是从高地址向低地址生长的,如果STACK_START是栈的高地址起始点、STACK_END是低地址边界,原循环src < dst的判断完全错误,应该改为src > dst,从高地址向低地址填充。
  • 类型未明确:src和dst未声明为unsigned long*类型,会导致地址操作的类型不匹配问题。

2. 栈统计的计算与逻辑错误

  • 生长方向判断错误:统计时应该从栈的高地址起始点STACK_START向下(低地址)查找第一个非0xDEADBEEF的位置,而不是向上递增查找。
  • 字节数计算错误:countBytes每次递增1,但unsigned long是4字节(多数架构),剩余栈字节数应该是countWords * sizeof(unsigned long),原代码直接用计数当作字节数,结果会缩小为实际值的1/4。
  • 返回值未定义:函数最后返回c,但c从未声明,属于未定义行为。

3. STACK_SIZE与地址边界不匹配

如果STACK_SIZE是栈的总字节数,必须保证STACK_END = STACK_START - STACK_SIZE(栈高地址起始的场景),否则STACK_SIZE和实际填充的栈空间大小不对应,修改STACK_SIZE时结果必然混乱。


修正后的示例代码

栈填充代码(栈从高地址向低地址生长场景)

// 明确指针类型,避免类型不匹配
volatile unsigned long *src = (volatile unsigned long*)STACK_START;
volatile unsigned long *dst = (volatile unsigned long*)STACK_END;

// 从高地址向低地址填充哑值
while(src > dst){  
  *(src--) = 0xDEADBEEF;
}

栈统计代码

uint32_t StackCount(void)
{  
    volatile unsigned long *start = (volatile unsigned long*)STACK_START;
    volatile unsigned long *end = (volatile unsigned long*)STACK_END;
    uint32_t countWords = 0;

    // 从栈起始高地址向下查找第一个被覆盖的位置
    while(start > end && *start == 0xDEADBEEF)
    {
        start--;
        countWords++;                
    }
        
    // 转换为字节数计算
    uint32_t remainingBytes = countWords * sizeof(unsigned long);
    uint32_t usedBytes = STACK_SIZE - remainingBytes;
    
    printf("stack used:%d bytes \n", usedBytes);
    printf("remaining stack :%d bytes\n", remainingBytes);
         
    return usedBytes;
}

额外注意事项

  • 确认链接脚本中的栈定义:比如多数场景下,栈的起始地址是_estack,STACK_END需计算为(uint8_t*)_estack - STACK_SIZE,保证和STACK_SIZE对应。
  • 统计时机:必须在程序运行过所有最坏场景(如中断嵌套、最深函数调用)后再调用统计函数,否则得到的不是最大栈使用率。
  • 编译器优化:保持volatile修饰指针,避免填充或统计代码被编译器优化掉。

内容的提问来源于stack exchange,提问作者shakingwindow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:10:20