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字节提前预测功能!在堆即将用完之前预警!

我不相信神话,我只相信汗水!我不相信命运,我只相信双手!
分类: 物联网

本文转自大石头博客园博客,原文链接:http://www.cnblogs.com/nnhy/p/memory.html,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
缓存
非连续内存分配
非连续内存分配
17 0
|
4月前
|
Python
pwn06(关于64位程序堆栈平衡的处理)
pwn06(关于64位程序堆栈平衡的处理)
43 0
|
6月前
|
存储 算法 C语言
5.堆栈算法
5.堆栈算法
|
11月前
|
API
驱动开发:内核远程堆分配与销毁
在开始学习内核内存读写篇之前,我们先来实现一个简单的内存分配销毁堆的功能,在内核空间内用户依然可以动态的申请与销毁一段可控的堆空间,一般而言内核中提供了`ZwAllocateVirtualMemory`这个函数用于专门分配虚拟空间,而与之相对应的则是`ZwFreeVirtualMemory`此函数则用于销毁堆内存,当我们需要分配内核空间时往往需要切换到对端进程栈上再进行操作,接下来`LyShark`将从API开始介绍如何运用这两个函数实现内存分配与使用,并以此来作为驱动读写篇的入门知识。
209 0
|
11月前
|
API
10-FreeRTOS堆栈溢出
10-FreeRTOS堆栈溢出
理论:第十三章:堆溢出,栈溢出的出现场景以及解决方案
理论:第十三章:堆溢出,栈溢出的出现场景以及解决方案
123 0
理论:第十三章:堆溢出,栈溢出的出现场景以及解决方案
|
Java 调度
【设计一个刚好在一秒堆溢出的程序】
【设计一个刚好在一秒堆溢出的程序】
【设计一个刚好在一秒堆溢出的程序】
|
存储 IDE 编译器
函数内部分配的buffer过大导致堆栈溢出
函数内部分配的buffer过大导致堆栈溢出
358 0
函数内部分配的buffer过大导致堆栈溢出
|
iOS开发 Android开发 Linux
定位堆内存越界问题
定位堆内存越界问题 堆内存崩溃俗称采坑。也就是说在前面某些地方埋了坑,却不知道代码位置,但是等崩溃出现了,却看到的是踩坑的代码。 这时候我们需要找到埋坑的地方。然后修复埋坑的代码。 Windows: 如果是Debug版,dbgheap.c 在堆内存前后会加 8个0xcd 保护值。
4769 0