关于0字节的内存泄露 与 0字节的内存申请

时间:2022-04-27 17:04:48

今天继续看内核,发现有0字节的内存分配,觉得有点奇怪.自己写了一个测试程序.

 

void CTestDlg::OnOK()

{

char *p = (char*)malloc(0);

free(p);

}

发现居然是可以通过编译的,且分配的指针p有效.看了一下MSDN的malloc的描述:

If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item.

 

既然用户传0,malloc还分配一个有效内存地址,那这地址一定是内存控制块了.内存控制块应该是一段size很小的空间,起个运行时校验作用,由校验数据和校验码组成,这是个人推断了,MSDN上未有内存控制块的组成说明.下面我们会以代码验证这个推断.

 

char *p = (char*)malloc(0);

*p = 100;//改写了控制块的内存

return;//不释放

 

不释放自然不会有运行时库的堆检查了.但这种作法产生了0字节的内存泄露.

Detected memory leaks!
Dumping objects ->
{80} normal block at 0x00382FB8, 0 bytes long.
 Data: <>
Object dump complete.

 

CSDN上有人曾有这种疑惑,但是未有人正确解答.见如下帖.

http://topic.csdn.net/u/20090310/20/0489b016-6425-4b15-a093-ea67cf75e15f.html

甚至有人说C++不允许new出0字节内存,我也试了一下,发现new0字节是可以的.

char *p = new char[0];

 

加上释放代码:

char *p = (char*)malloc(0);

*p = 100;//改写了控制块的内存

free(p);

return;

结果断言错误.

DAMAGE:after Normal block(#88) at 0x00382FB2

能看到的代码在crt/src/dbgheap.c 1178行 free调用_free_dbg函数。实现的代码看不到了。

原因是损坏了内存控制块。

 

改成如下方式:

char *p = (char*)malloc(0);

int a = *p; //保存块数据

//其它操作代码

*p = a;//释放前还原控制块

free(p);

return;

执行并退出程序,可以看到一切正常了。

 

最后回到内核代码8390.h alloc_eip_netdev(void)调用__alloc_eip_netdev(0);

struct net_device *__alloc_eip_netdev(int size)

{

struct net_device *dev = __alloc_ei_netdev(size);

if(dev)

  dev->netdev_ops = &eip_netdev_ops;

return dev;

}

可以看到内核分配了0字节而且改写了。但为什么没出问题呢?

只有继续研究,等弄通后再在下一篇来解决这个疑惑了.