无数次遭受堆栈溢出折磨,随着系统变得复杂,故障点越来越难以查找!
主要溢出情况如下:
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字节提前预测功能!在堆即将用完之前预警!

End.

                                转载石头大哥

STM32/GD32上内存堆栈溢出探测研究的更多相关文章

  1. 通过map文件了解堆栈分配(STM32、MDK5)--避免堆栈溢出

    环境:STM32F103C8T6,MDK5 在最近的一个项目的开发中,每当调用到一个函数,程序就直接跑飞.debug跟进去看不出什么逻辑错误,但发现函数内局部变量声明之后,全局变量的值被清零,后来查看 ...

  2. arcgis engine 中出现的内存堆栈溢出问题。

    两种解决方案: 1.循环加载mxd文档的时候出现的堆栈溢出,解决办法是每次循环结束时清空FeatureLayer,感觉并不好,但是确实可以实现功能. 2.循环调取featureclass的search ...

  3. STM32堆栈溢出

    在使用STM32读取SD Card的文件时,总是会卡死在读函数那里 res = f_read(&fsrc, gbuffer, sizeof(gbuffer)-1, &br); 而且出现 ...

  4. STM32片上Flash内存映射、页面大小、寄存器映射

    STM32片上Flash内存映射.页面大小.寄存器映射 STM32有4种Flash module organization,分别是:low-density devices(32KB,1KB/page) ...

  5. 前端知识体系:JavaScript基础-作用域和闭包-闭包的实现原理和作用以及堆栈溢出和内存泄漏原理和相应解决办法

    闭包的实现原理和作用 闭包: 有权访问另一个函数作用域中的变量的函数. 创建闭包的常见方式就是,在一个函数中创建另一个函数. 闭包的作用: 访问函数内部变量.保持函数在环境中一直存在,不会被垃圾回收机 ...

  6. CC_STACKPROTECTOR防内核堆栈溢出补丁分析【转】

    转自:https://yq.aliyun.com/articles/1723 摘要: 作者:王智通   CC_STACKPROTECT补丁是Tejun Heo在09年给主线kernel提交的一个用来防 ...

  7. Javascript中递归造成的堆栈溢出及解决方案

    关于堆栈的溢出问题,在Javascript日常开发中很常见,Google了下,相关问题还是比较多的.本文旨在描述如何解决此类问题. 首先看一个实例(当然你可以使用更容易的方式实现,这里我们仅探讨递归) ...

  8. STM32/GD32芯片信息(转)

    源:STM32/GD32芯片信息 因为需要自动适配芯片进行系统配置,所以我们有必要通过读取一些系统寄存器来获取必要信息.我们的代码需要兼容STM32F1/GD32F1/STM32F0/STM32F4 ...

  9. 如何解决js递归里面出现的堆栈溢出

    16.下面的递归代码在数组列表偏大的情况下会导致堆栈溢出.在保留递归模式的基础上,你怎么解决这个问题? var list = readHugeList(); var nextListItem = fu ...

随机推荐

  1. PHP的基本语法

    PHP的基本语法和c#的基本语法是差不多的,在这里只和大家聊一下PHP和C#语法不同的地方. 首先 PHP和c#的标记方式不一样,PHP他是一门脚本语言,JS也是脚本语言,只不过JS是运行在客户端的, ...

  2. <s:iterator> 对list操作的一种方法

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA6IAAAH3CAIAAAAuRnW9AAAgAElEQVR4nOzdf4gk1333+wLDDffhPp

  3. C++如何通过一个响应事件接受多个控件消息

    在空的Form里加个Button,写入void __fastcall TForm1::Button1Click(TObject *Sender){ for (long k=0; k<5; k++ ...

  4. The golden ratio: 1.618

    http://www.chinaz.com/design/2015/1109/467968_2.shtml The golden ratio: 1.618 a/b=b/(a+b) The Fibona ...

  5. editPlus修改默认的文件编码

  6. 系统配置SQL profile

    select M.RESPONSIBILITY_NAME, B.PROFILE_OPTION_NAME, X.USER_PROFILE_OPTION_NAME, t.profile_option_va ...

  7. (转)oracle 查看表所占用的空间大小

    1.查看表所占空间 SELECT   TABLESPACE_NAME,TO_CHAR(SUM(BYTES)/(1024*1024),'999G999D999')   CNT_MB     FROM   ...

  8. spring的事务回滚

    @Transactional(rollbackFor = { Exception.class }) 需要把异常抛出到带有@Transactional(rollbackFor = { Exception ...

  9. SqlServer中使用Select语句给变量赋值的时候需要注意的一个问题

    我们知道在SqlServer中可以用Select语句给变量赋值,比如如下语句就为int类型的变量@id赋值 ; select @id=id from ( as id union all as id u ...

  10. nginx负载均衡的实现

    将一台nginx主机当作前端负载均衡服务器,后面通过交换机链接多台web服务器,提供html和php的web界面服务.通过配置前端负载均衡服务器,可以实现将html界面和php界面的分开访问,即htm ...