zoukankan      html  css  js  c++  java
  • STM32/GD32上内存堆栈溢出探测研究

    无数次遭受堆栈溢出折磨,随着系统变得复杂,故障点越来越难以查找!
    主要溢出情况如下:
    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.

                                    转载石头大哥

  • 相关阅读:
    JUnit单元测试--IntelliJ IDEA
    sublime Error executing: /usr/bin/security dump-trust-settings -d
    git 撤销commit
    mockito 初识
    Lucene 初识
    从list中随机选出几个数,并按照原来的顺序排列
    JVM原理
    JVM crash at ForUtil.readBlock
    Scrum之初体验
    Mac安装Gradle eclipse安装buildship插件
  • 原文地址:https://www.cnblogs.com/Ph-one/p/3960940.html
Copyright © 2011-2022 走看看