图2. Heap的包装数据组织以检测是否heap被破坏
图2中的size域值是用于free()函数来找到该魔幻数字的,如下面的实例代码所示。包装函数用8个字节的额外开销来记载heap的结构。下例重新实现了C++中的new和delete函数。
#include <stdint.h>
#include <stdlib.h>
#define MAGIC_NUMBER 0xefdcba98
uint32_t myMallocMaxMem;
void* MyMalloc(size_t bytes)
{
uint8_t *p, *p_end;
static uint8_t* mLow = (uint8_t*)0xffffffff; /* lowest address
returned by malloc() */
static uint8_t* mHigh; /* highest address + data returned by
malloc() */
bytes = (bytes + 3) & ~3; /* ensure alignment for magic number */
p = (uint8_t*)malloc(bytes + 8); /* add 2x32-bit for size and
magic number */
if (p == NULL)
{
abort(); /* out of memory */
}
*((uint32_t*)p) = bytes; /* remember size */
*((uint32_t*)(p + 4 + bytes)) = MAGIC_NUMBER; /* write magic number after user allocation */
/* crude method of estimating maximum used size since application start */
if (p < mLow) mLow = p;
p_end = p + bytes + 8;
if (p_end > mHigh) mHigh = p_end;
myMallocMaxMem = mHigh - mLow;
return p + 4; /* allocated area starts after size */
}
void MyFree(void* vp)
{
uint8_t* p = (uint8_t*)vp - 4;
int bytes = *((uint32_t*)p);
/* check that magic number is not corrupted */
if (*((uint32_t*)(p + 4 + bytes)) != MAGIC_NUMBER)
{
abort(); /* error: data overflow or freeing already freed
memory */
}
*((uint32_t*)(p + 4 + bytes)) = 0; /* remove magic number to be
able to detect freeing already freed memory */
free(p);
}
#ifdef __cplusplus
// global override of operator new, delete, new[] and delete[]
void* operator new (size_t bytes) { return MyMalloc(bytes); }
void operator delete (void *p) { MyFree(p); }
#endif
需要说明的是,上面的实例能避免之前提到的错误是在分配的内存也被释放的前提下。但有些应用并不如此,这就需要添加另外的域来维护当前系统中分配的内存区域,然后周期性的验证分配内存记录的合理性。这个附加的列示当前动态内存分配的表不会太长因为对于嵌入式系统而言,只需要使用次数相对较少的动态内存。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。