当调用C语言的Free函数时,C会做些什么动作?

darksun9972 2011-01-09 11:55:34
最近按照书上说的,尝试封装了一下C语言的malloc和free函数,代码如下:
[myMallocFree.h:]
#ifndef __MYMALLOCFREE_H__
#define __MYMALLOCFREE_H__
enum myFreeErr
{
myFreeErr_SUCESS=0,/**内存释放成功*/
myFreeErr_DELETED=1,/**指定内存已经释放过了*/
myFreeErr_UNMALLOC=-1,/**指定内存为未分配内存*/
};
typedef enum myFreeErr myFreeErr;
#define TAG_LEN 4
static const char useTag[TAG_LEN]={'U','S','E','D'};
static const char deleteTag[TAG_LEN]={'\0','D','E','L'};
void* myMalloc(size_t sizeToMalloc);
myFreeErr myFree( void *returnAddress );
#endif




[myMallocFree.c:]
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include "myMallocFree.h"

/**typedef unsigned int size_t*/
void* myMalloc(size_t sizeToMalloc)
{
void* mallocAddress=NULL;
void* returnAddress=NULL;
if(sizeToMalloc<=0)
{
printf("分配的内存数必须大于0\n");
return NULL;
}
mallocAddress=malloc(sizeToMalloc+TAG_LEN);
if(mallocAddress==NULL)
{
printf("分配内存失败!\n");
return NULL;
}
else
{
/**设置内存分配成功的标签*/
memcpy(mallocAddress,useTag,TAG_LEN);
returnAddress=(char *)mallocAddress+TAG_LEN;
#ifdef __DEBUG__
printf("分配内存mallocAddress=%d,returnAddress=%d\n",mallocAddress,returnAddress);
#endif
return returnAddress;
}
}

myFreeErr myFree( void *returnAddress )
{
/**检查标志*/
char tagOfPtr[TAG_LEN+1]={'\0'};
void* mallocAddress=NULL;
mallocAddress=(char *)returnAddress-TAG_LEN;
memcpy(tagOfPtr,mallocAddress,TAG_LEN);
#ifdef __DEBUG__
printf("tagOfPtr=[%s]\n",tagOfPtr);
#endif
/**若为已分配的内存*/
if(memcmp(tagOfPtr,useTag,TAG_LEN)==0)
{
/**则修改标志为已删除*/
memcpy(mallocAddress,deleteTag,TAG_LEN);
/**删除所有内存*/
free(mallocAddress);
/**并返回"删除成功标识" */
#ifdef __DEBUG__
printf("return myFreeErr_SUCESS\n");
#endif
return myFreeErr_SUCESS;
}
/**若为已经删除过的内存*/
else if(memcmp(tagOfPtr,deleteTag,TAG_LEN)==0)
{
/**则返回"已经删除标识"*/
#ifdef __DEBUG__
printf("return myFreeErr_DELETED\n");
#endif
return myFreeErr_DELETED;
}
/**否则返回"非分配内存标识" */
else
{
#ifdef __DEBUG__
printf("return myFreeErr_UNMALLOC\n");
#endif
return myFreeErr_UNMALLOC;
}
}




[myMallocFreeTest.c:]
#include <stdlib.h>
#include <Stdio.h>
#include <string.h>
#include <assert.h>
#include "myMallocFree.h"

int main()
{
char *chPtr=NULL;
char tagOfPtr[TAG_LEN]={'\0'};
chPtr=myMalloc(20);
if(chPtr==NULL)
{
printf("do myMalloc failed\n");
return 0;
}
if(memcmp(chPtr-TAG_LEN,useTag,TAG_LEN)!=0)
{
printf("myMalloc wrong!\n");
}
if(myFree(chPtr)!=myFreeErr_SUCESS)
{
printf("myFree wrong!(myFreeErr_SUCESS step)\n");
}
if(myFree(chPtr)!=myFreeErr_DELETED)
{
printf("myFree wrong!(myFreeErr_DELETED step)\n");
}
if(myFree(tagOfPtr)!=myFreeErr_UNMALLOC)
{
printf("myFree wrong!(myFreeErr_UNMALLOC step)\n");
}
system("pause");
return 0;
}
在用myMallocFreeTest.c做测试的时候总是报myFree wrong!(myFreeErr_DELETED step)
但是我不知道到底哪出问题了
怀疑是在调用Free函数时C对内存块做了一些操作破坏了设置的标记吧,但是不知道到底做了哪些操作。
求各位大神解答一下~~~谢谢了
...全文
169 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
xi_hz 2011-02-27
  • 打赏
  • 举报
回复
以下这段代码的测试,或许会让你有所了解
#include <stdio.h>
#include <stdlib.h>

typedef struct _node
{
int value;
char ch;
struct _node* next;
} node, *pnode;

int main(int argc, char* argv[])
{
pnode head = NULL;
head = (pnode)malloc(sizeof(node));
head->value =121;
head->ch ='h';
printf("head->value=%d\n",head->value);
printf("head->ch=%c\n",head->ch);

free(head);
//??在free(head)释放完成后,还可以使用head??
printf("head->value=%d\n",head->value);
printf("head->ch=%c\n",head->ch);
//??重新申请空间,占用了head的内存空间
pnode p = NULL;
p = (pnode)malloc(sizeof(node));
p->value =19;
p->ch ='l';
//??但是head还是可以用,只是打印出来的是p的值而已
printf("head->value=%d\n",head->value);
printf("head->ch=%c\n",head->ch);

head->value = 22;
//??通过head还是修改该段内存的值。
printf("head->value=%d\n",head->value);
printf("head->ch=%c\n",head->ch);
system("pause");
return 0;
}

wizard_tiger 2011-01-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lujun9972 的回复:]
引用 1 楼 lthyxy 的回复:
当调用C语言的Free函数时,C会做些什么动作?
调用内核,释放内存

能具体说说释放内存的动作么?比如他是怎么检查出来需要释放多大的内存?释放内存的时候,是不是会把这一块内存的内容清空?还是在这块内存的某个位置做个什么标记之类的。
[/Quote]
应该不会把内存的内容清空,只是做一个标记告诉系统这块内存可用,至于释放多大内存,应该是在申请时就有标记说明申请了多大。
darksun9972 2011-01-10
  • 打赏
  • 举报
回复
dooX8086兄说的很对啊,在多进程操作系统环境下,被释放的内存块很有可能就被别的进程使用了,所以没办法保证内容,而且对于使用来说也没必要区分是被删除的还是没有分配的情况。这个是我没有考虑清楚的,谢谢你的提醒啊~~
dooX8086 2011-01-09
  • 打赏
  • 举报
回复
下面为个人对这段代码的理解.

//...
if(myFree(chPtr)!=myFreeErr_SUCESS) // 这里 free 了一次 chPrt.
{
printf("myFree wrong!(myFreeErr_SUCESS step)\n");
}

if(myFree(chPtr)!=myFreeErr_DELETED) //因为上面已经 free 了一次, 所以 chPrt (现在是野指针)指向内存的数据是得不到保证的 .. 再看myFree 函数 =======>>>>>>>>
{
printf("myFree wrong!(myFreeErr_DELETED step)\n");
}
//...


//function myFree: 代码段 //<<<<<<==========
/**若为已分配的内存*/
if(memcmp(tagOfPtr,useTag,TAG_LEN)==0)
{
/**则修改标志为已删除*/
memcpy(mallocAddress,deleteTag,TAG_LEN);
/**删除所有内存*/
free(mallocAddress); //-----也就这里..第一次正确地 free 了,以后这段内存的数据说得不到保证了
/**并返回"删除成功标识" */
#ifdef __DEBUG__
printf("return myFreeErr_SUCESS\n");
#endif
return myFreeErr_SUCESS;
}
/**若为已经删除过的内存*/
else if(memcmp(tagOfPtr,deleteTag,TAG_LEN)==0) //在第二次 用myFree 时这个 tagOfPtr 是野指针非法的
{
/**则返回"已经删除标识"*/
#ifdef __DEBUG__
printf("return myFreeErr_DELETED\n");
#endif
return myFreeErr_DELETED;
}
//..


猜测性. 采用非法 对 非法手段.可能某些平台能行..(呵呵 纯属猜测)

// 在 myFree 函数中
//...
//function myFree: 代码段 //<<<<<<==========
/**若为已分配的内存*/
if(memcmp(tagOfPtr,useTag,TAG_LEN)==0)
{
/**删除所有内存*/
free(mallocAddress); //<<<--------下面的 free 放到了这里

/**则修改标志为已删除*/
memcpy(mallocAddress,deleteTag,TAG_LEN);

//free(mallocAddress); //这是原来的,把它放到上面 //------>>>>

//...


// 既然自己维护内存(内存池),那就不应该真地去 free 掉内存, 写入delete 标记就行了
liutengfeigo 2011-01-09
  • 打赏
  • 举报
回复
我还没学操场系统。不清楚啊
darksun9972 2011-01-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lthyxy 的回复:]
当调用C语言的Free函数时,C会做些什么动作?
调用内核,释放内存
[/Quote]
能具体说说释放内存的动作么?比如他是怎么检查出来需要释放多大的内存?释放内存的时候,是不是会把这一块内存的内容清空?还是在这块内存的某个位置做个什么标记之类的。
liutengfeigo 2011-01-09
  • 打赏
  • 举报
回复
当调用C语言的Free函数时,C会做些什么动作?
调用内核,释放内存

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧