STM32 堆栈溢出问题

STM32 堆栈溢出问题

当我们创建稍微复杂一点的系统时,堆栈溢出问题极易出现!

1、一般RAM最后两块空间是堆heap、栈stack,堆从下往上用,栈从上往下用,任意 一个用完都会进入对方空间。

2、如果栈用完,进入堆空间,这个时候系统是不会有任何异常的,也就是说,栈底是没有什么意义的。除非堆和栈指针重叠,否则一切正常,尽管栈指针指向了堆空间。

3、如果栈用完,进入堆的空间,这个时候系统是不会有异常的,但是堆栈会相互修改数据。最难受的就是,栈里面保存的指针地址,一旦被堆空间修改了栈空间中的指针数据,当再次调用占空间中的地址指针时,会跳到无效的内存空间中去,然而这个时候,系统仍然不会报错,但系统运行和数据已经错乱了。

4、如果使用KEIL微库,堆空间用完,再malloc的时候,会得到空指针,但是不会报错。然而如果使用C++的new,这个时候会报错。

以下代码是内存堆栈溢出检测模块。

#ifdef DEBUG

void* operator new(uint size);
void* operator new[](uint size);
void operator delete(void * p);
void operator delete [] (void * p);

#endif
extern uint __heap_base;
extern uint __heap_limit;

void* operator new(uint size)
{
    debug_printf(" new size: %d ", size);
    void * p = malloc(size);
    if(!p)
        debug_printf("malloc failed! size=%d ", size);
    else
    {
        debug_printf("0x%08x ", p);
        // 如果堆只剩下64字节,则报告失败,要求用户扩大堆空间以免不测
        uint end = (uint)&__heap_limit;
        if((uint)p + size + 0x40 >= end) debug_printf(" + %d near HeapEnd=0x%08x", size, end);
    }
    assert_param(p);
    return p;
}

void* operator new[](uint size)
{
    debug_printf(" new size[]: %d ", size);
    void * p = malloc(size);
    if(!p)
        debug_printf("malloc failed! size=%d ", size);
    else
    {
        debug_printf("0x%08x ", p);
        // 如果堆只剩下64字节,则报告失败,要求用户扩大堆空间以免不测
        uint end = (uint)&__heap_limit;
        if((uint)p + size + 0x40 >= end) debug_printf(" + %d near HeapEnd=0x%08x", size, end);
    }
    assert_param(p);
    return p;
}

void operator delete(void * p)
{
    debug_printf(" delete 0x%08x ", p);
    if(p) free(p);
}

void operator delete[](void * p)
{
    debug_printf(" delete[] 0x%08x ", p);
    if(p) free(p);
}```

## 5、我们在实际使用过程中,可能不会像上面一样再去封装检测函数,那这个时候需要我们自己去多多注意相关的问题。
①比如函数调用纵深不宜过深,五个左右为最高。其次,局部变量不要太多太大,尤其是局部数组,大容量的数组定义为全局变量,减少栈空间的占用。
②堆的问题。如果堆空间较小,而需要中间缓存malloc的空间很大,这个时候,很容易导致堆指针指向栈空间,修改栈内数据,导致运行错误。所以,我们要评估我们的malloc缓存空间,在free之前,同时可能存在的最大内存为多少,然后修改启动文件中对应的size,减少系统出错的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值