认识 free指针背后
2009-09-03 22:58
176 查看
本文摘自:http://blog.csdn.net/lfkupc/archive/2009/02/23/3925764.aspx
malloc和free在教材里不知讲了多少,今天实际用到一处,就出问题了。
案发现场是我用VC++在WINXP下编程,先看这一段代码
{
BYTE *pBuffer;
pBuffer = (BYTE *)malloc(64);
pBuffer = pBuffer + 32;
free(pBuffer);
pBuffer = NULL;
} //第一段
先声明一个指针,然后分配64字节给它。操作指针向后移动32字节,最后把这个指针free掉并设为NULL。这样虽然操作时的数据还留在内存区域里,但已经没有指针指向该区域,数据可以被后面的程序覆盖了。看起来没错吧?恩恩好象是没错, 抓了三个同事来问,全票通过. 但在实际上呢, 运行时会跳出。
而如果把代码改成
{
BYTE *pBuffer;
pBuffer = (BYTE *)malloc(64);
pBuffer = pBuffer + 32;
pBuffer = pBuffer -32;
free(pBuffer);
pBuffer = NULL;
} //第二段代码
就没错了。李博士的解释是:malloc的时候系统创建了一个链表之类的东西,里面包含了起始地址和长度;而free的时候根据参数中的指针进行判断,如果该指针符合链表中某一节的起始地址,那么就把这一节free掉,如果去free一个不在链表中的地址,就出错啦。
比较好的处理方式是这样
{
BYTE *pBuffer;
BYTE *pBytePtr;
pBuffer = (BYTE *)malloc(64);
pBytePtr = pBuffer;
pBytePtr = pBytePtr + 32;
free(pBuffer);
pBuffer = NULL;
pBytePtr = NULL;
} //第三段代码
即保留malloc时候的初始地址,然后赋给另外一个临时指针。操作时使用后者。free的时候把保留的起始指针free掉,而临时指针只是个变量,置空就可以了。
文章到这里似乎就应该写完了,不过由于johnathan的帮忙, 突然有了下文。
注意警告框中的_CrtIsValidHeapPointer,在MSDN上查到这个函数的说明为:
Verifies that a specified pointer is in the local heap (debug version only).
int _CrtIsValidHeapPointer(const void *userData);
Parameter:
userData Pointer to the beginning of an allocated memory block.
Return Value:
_CrtIsValidHeapPointer returns TRUE if the specified pointer is in the local heap. Otherwise, the function returns FALSE.
也就是说仅在debug版本中检查free参数是否为the beginning of an allocated memroy block.
那么就编译一个release版本,果然,运行通过, 没弹出什么警告或错误。但运行通过不等于正常无误, 博士认为这就是无声无息导致内存泄露的罪魁祸首. 即使release版里面也应该free起始地址.
那么结论就是:free掉非malloc起始地址的指针,在debug版本中会出错警告,而在release版本中不会弹出警告但仍然是有错的。所以,还是推荐使用第三段代码的用法
malloc和free在教材里不知讲了多少,今天实际用到一处,就出问题了。
案发现场是我用VC++在WINXP下编程,先看这一段代码
{
BYTE *pBuffer;
pBuffer = (BYTE *)malloc(64);
pBuffer = pBuffer + 32;
free(pBuffer);
pBuffer = NULL;
} //第一段
先声明一个指针,然后分配64字节给它。操作指针向后移动32字节,最后把这个指针free掉并设为NULL。这样虽然操作时的数据还留在内存区域里,但已经没有指针指向该区域,数据可以被后面的程序覆盖了。看起来没错吧?恩恩好象是没错, 抓了三个同事来问,全票通过. 但在实际上呢, 运行时会跳出。
而如果把代码改成
{
BYTE *pBuffer;
pBuffer = (BYTE *)malloc(64);
pBuffer = pBuffer + 32;
pBuffer = pBuffer -32;
free(pBuffer);
pBuffer = NULL;
} //第二段代码
就没错了。李博士的解释是:malloc的时候系统创建了一个链表之类的东西,里面包含了起始地址和长度;而free的时候根据参数中的指针进行判断,如果该指针符合链表中某一节的起始地址,那么就把这一节free掉,如果去free一个不在链表中的地址,就出错啦。
比较好的处理方式是这样
{
BYTE *pBuffer;
BYTE *pBytePtr;
pBuffer = (BYTE *)malloc(64);
pBytePtr = pBuffer;
pBytePtr = pBytePtr + 32;
free(pBuffer);
pBuffer = NULL;
pBytePtr = NULL;
} //第三段代码
即保留malloc时候的初始地址,然后赋给另外一个临时指针。操作时使用后者。free的时候把保留的起始指针free掉,而临时指针只是个变量,置空就可以了。
文章到这里似乎就应该写完了,不过由于johnathan的帮忙, 突然有了下文。
注意警告框中的_CrtIsValidHeapPointer,在MSDN上查到这个函数的说明为:
Verifies that a specified pointer is in the local heap (debug version only).
int _CrtIsValidHeapPointer(const void *userData);
Parameter:
userData Pointer to the beginning of an allocated memory block.
Return Value:
_CrtIsValidHeapPointer returns TRUE if the specified pointer is in the local heap. Otherwise, the function returns FALSE.
也就是说仅在debug版本中检查free参数是否为the beginning of an allocated memroy block.
那么就编译一个release版本,果然,运行通过, 没弹出什么警告或错误。但运行通过不等于正常无误, 博士认为这就是无声无息导致内存泄露的罪魁祸首. 即使release版里面也应该free起始地址.
那么结论就是:free掉非malloc起始地址的指针,在debug版本中会出错警告,而在release版本中不会弹出警告但仍然是有错的。所以,还是推荐使用第三段代码的用法
相关文章推荐
- 认识 free指针背后(释放内存大小问题)
- free一个无效指针
- 重磅 | FreeBuf 发布黑镜调查:深渊背后的真相之「薅羊毛产业」报告
- 指针简单认识
- free指针时遭遇_CrtIsValidHeapPointer
- c++对指针的认识
- free 或delete后指针怎么样了
- 安全的指针FREE
- 谈谈我对指针的认识
- free和delete把指针怎么啦?
- 7.5 free 和delete 把指针怎么啦?
- c/c++中的指针你认识多少?
- 一级二级指针new、delete、malloc、free
- 认识DOM文档的遍历指针以及如何获取根节点和body节点
- 在C++动态库中释放调用动态库程序中生成的指针new和delete 或 malloc和free
- C语言指针数组和数组指针粗浅认识
- 指针的认识
- c++中函数参数传递(值传递、指针传递,引用传递)进一步认识
- c++智能指针,从源码开始认识
- 从一个简单程序的GDB调试看段错误,指针的初始化及内存分配(malloc/free)