STM32/GD32上内存堆栈溢出探测研究

简介: 无数次遭受堆栈溢出折磨,随着系统变得复杂,故障点越来越难以查找!主要溢出情况如下:1,一般RAM最后两块空间是堆Heap和栈Stack,堆从下往上用,栈从上往下用,任意一个用完,都会进入对方的空间2,如果栈用完,进入堆的空间,这个时候系统是不会有任何异常的,也就是说,栈底没有什么意义。
+关注继续查看

无数次遭受堆栈溢出折磨,随着系统变得复杂,故障点越来越难以查找!
主要溢出情况如下:
1,一般RAM最后两块空间是堆Heap和栈Stack,堆从下往上用,栈从上往下用,任意一个用完,都会进入对方的空间
2,如果栈用完,进入堆的空间,这个时候系统是不会有任何异常的,也就是说,栈底没有什么意义。除非堆和栈指针重叠,否则大家相安无事,尽管栈用了堆的
3,如果栈用完进入堆,并且还碰到了堆的空间,这个时候系统仍然没有异常,但是堆栈会相互修改数据。最悲剧的就是栈里面保存的然会地址lr,一旦被堆指针修改,返回的时候就会跳到别的地址空间去了。绝大多数时候是这种情况,并且大多数跳到无效空间去。你应该感谢它跳到无效空间,让你马上发现错误。否则堆栈互相穿透而不报错,然后系统工作出现数据错乱,到时候看你想撞头还是想跳楼!
4,使用Keil的微库,malloc要用到堆空间,如果堆空间用完,再malloc的时候得到空指针,但是不会报错。然而,如果使用C++的new,这个时候会报错!

因为主线程和中断处理的存在,随时可能分配释放内存,这就导致了问题随时可能发生!非常难检查问题所在!

因此,SmartOS v2.5增加了内存堆栈溢出探测模块
声明:

#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);
}

通过重载new/delete实现,并且带有64字节提前预测功能!在堆即将用完之前预警!

我不相信神话,我只相信汗水!我不相信命运,我只相信双手!
相关文章
|
5月前
|
存储 JSON 自然语言处理
JS进阶(二)JS底层运行机制之堆栈内存
1.JS底层运行机制之堆(Heap)栈(Stack)内存 相关理论知识 ECStack(Execution context Stack) 执行环境栈: —— 内存中分出来用于执行js代码的空间 EC(Execution context): —— 执行上下文, 为了区分全局和函数执行所处的不同范围(词法作用域),又可以分为全局执行上下文EC(G)和函数执行私有上下文EC(FUNC) 作者:重阳微噪 链接:https://juejin.cn/post/6850418109707190285 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
95 0
|
7月前
|
机器学习/深度学习 人工智能 缓存
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南(3)
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南
197 0
|
7月前
|
机器学习/深度学习 人工智能 算法
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南(2)
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南
|
7月前
|
机器学习/深度学习 存储 人工智能
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南(1)
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南
|
10月前
|
C语言
C语言内存及堆栈操作
C语言内存及堆栈操作
57 0
C语言内存及堆栈操作
|
12月前
|
存储 JSON JavaScript
深入理解js数据类型与堆栈内存(下)
深入理解js数据类型与堆栈内存(下)
深入理解js数据类型与堆栈内存(下)
|
12月前
|
JavaScript 前端开发 开发者
深入理解js数据类型与堆栈内存(上)
深入理解js数据类型与堆栈内存(上)
深入理解js数据类型与堆栈内存(上)
堆栈(Strack)是指这样一段内存,它可以理解为一个筒结构,先放进筒中的数据被后放进筒中的数据“压住”,只有后放进筒中的数据都取出后,先放进去的数据才能被取出,称为“后进先出”。堆栈的长度可随意增加
堆栈(Strack)是指这样一段内存,它可以理解为一个筒结构,先放进筒中的数据被后放进筒中的数据“压住”,只有后放进筒中的数据都取出后,先放进去的数据才能被取出,称为“后进先出”。堆栈的长度可随意增加
132 0
LyScript 实现对内存堆栈扫描
LyScript插件中提供了三种基本的堆栈操作方法,其中`push_stack`用于入栈,`pop_stack`用于出栈,而最有用的是`peek_stack`函数,该函数可用于检查指定堆栈位置处的内存参数,利用这个特性就可以实现,对堆栈地址的检测,或对堆栈的扫描等。
LyScript 实现对内存堆栈扫描
|
Prometheus 监控 Cloud Native
相关产品
云迁移中心
推荐文章
更多