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.

                                转载石头大哥

时间: 2024-08-05 19:37:40

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

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

环境:STM32F103C8T6,MDK5 在最近的一个项目的开发中,每当调用到一个函数,程序就直接跑飞.debug跟进去看不出什么逻辑错误,但发现函数内局部变量声明之后,全局变量的值被清零,后来查看局部变量地址已经超出栈的范围,于是确定是栈溢出.如果不稍微了解一下堆栈,在开发过程中可能碰到各种奇怪的错误. .map和startup.s文件 MAP 文件是程序的全局符号.源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方.任何时候使用,不需要有额外的程序进行支持. 在MDK5中,在项目中

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

闭包的实现原理和作用 闭包: 有权访问另一个函数作用域中的变量的函数. 创建闭包的常见方式就是,在一个函数中创建另一个函数. 闭包的作用: 访问函数内部变量.保持函数在环境中一直存在,不会被垃圾回收机制处理 因为函数内部声明 的变量是局部的,只能在函数内部访问到,但是函数外部的变量是对函数内部可见的,这就是作用域链的特点了. 子级可以向父级查找变量,逐级查找,找到为止 因此我们可以在函数内部再创建一个函数,这样对内部的函数来说,外层函数的变量都是可见的,然后我们就可以访问到他的变量了. <scr

windows堆栈溢出利用的七种方式

文本由 www.169it.com 搜集整理 windows下的堆栈溢出攻击和unix下的,原理基本相同.但是,由于windows用户进程地址空间分配和堆栈处理有其独立的特点,导致了windows 环境下堆栈溢出攻击时,使用的堆栈溢出字符串,与unix下的,区别很大.另外,windows的版本也导致了windows下的exploit不具有通用性.windows版本不同,而exploit使用了很多动态链接库里面的库函数,其地址都是与dll的版本有关系的.不同的dll版本,里面的库函数的偏移地址就可

堆栈溢出

1.基础知识. 在x86处理器中:EIP(Instruction Pointer)是指令寄存器,指向处理器下条等待执行的指令地址(代码段内的偏移量),每次执行完相应汇编指令EIP值就会增加. ESP(Stack Pointer)是堆栈指针寄存器,存放执行函数对应栈帧的栈顶地址(也是系统栈的顶部),且始终指向栈顶: EBP(Base Pointer)是栈帧基址指针寄存器,存放执行函数对应栈帧的栈底地址,用于C运行库访问栈中的局部变量和参数. 从物理上讲,堆栈是就是一段连续分配的内存空间.在一个程序

PHP对象在内存堆栈中的分配

PHP对象在内存堆栈中的分配 对象在PHP里面和整型.浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢?内存从逻辑上说大体上是分为4段,栈空间段.堆空间段.代码段.初始化静态段,程序里面不同的声明放在不同的内存段里面. 数据段(data segment)通常是指用来存放程序中已初始化且不为0的全局变量如:静态变量和常量 代码段(code segment / text segment)通常是指用来存放程序执行代码的一块内存区

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

关于堆栈的溢出问题,在Javascript日常开发中很常见,Google了下,相关问题还是比较多的.本文旨在描述如何解决此类问题. 首先看一个实例(当然你可以使用更容易的方式实现,这里我们仅探讨递归): function isEven (num) { if (num === 0) { return true; } if (num === 1) { return false; } return isEven(Math.abs(num) - 2); } //Outputs: true console

js堆栈溢出错误

function prompt() { var answer = prompt("What is your name","") if (answer) { alert("Hello, " + answer + "!"); } } 提示堆栈溢出.我就纳闷了. 反复测试之后,发现原来函数名不能命名为prompt. function prompttt() { var answer = prompt("What is you

《屏幕上的聪明决策》:4星。人类在手机/电脑上做选择的心理学研究的综述。不流畅的文本有助于理解和记忆,淘汰赛制可以有效降低选择后懊悔。

本书是人类在手机/电脑上做选择的心理学研究的综述,比较可信,有许多有趣的事实与结论.比较重要的结论有这么几个:1:人类对网站.文章的判断很大程度上以来瞬间感知和审美:2:不流畅的文本有助于理解和记忆:3:可选项太多的情况下,可以考虑淘汰赛制,每次让用户从4个选项中选择一个最满意的.这样可以有效降低选择后懊悔. 总体评价4星. 以下是书中一些重要的结论与信息的摘抄,#号后面是kindle电子书中的页码: 1:人的注意力已经成为“21世纪的低硫原油”.如果可以控制人类注意力的杠杆,那么你几乎可以获取

Delphi2010启动报错:‘displayNotification: 堆栈溢出

今天启动delphi2010报错: ‘displayNotification: 堆栈溢出 在网上搜索了下,解决方法: 1.清理IE的历史记录,删除浏览器缓存...一定要清楚默认浏览器的历史缓存,我平常用的是谷歌,系统默认的是360.......... 2.去掉delphi2010的欢迎界面(welcome page) 在注册表里找到 HKEY_CURRENT_USER\Software\codegear\BDS\7.0\Known IDE Packages删除右边的数据项: ($BDS)\Bin