您的位置:首页 > 其它

malloc函数与free函数

2014-11-23 15:06 218 查看
malloc函数与free函数
malloc函数
Malloc 向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针
1函数简介
原型
extern void *malloc(unsigned int num_bytes);
头文件
在TC2.0中可以用malloc.h或 alloc.h (注意:alloc.h 与 malloc.h 的内容是完全一致的),而在Visual C++6.0中可以用malloc.h或者stdlib.h
功能
分配长度为num_bytes字节的内存
返回值
如果分配成功,则返回指向被分配内存的指针(此存储区中的初始值不确定);否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。函数返回的指针一定要适当对齐,使其可以用于任何数据对象
说明
关于该函数的原型,在旧的版本中malloc返回的是char型指针,新的ANSIC标准规定,该函数返回为void型指针,因此必要时要进行类型转换。
名称解释
malloc的全称是memory allocation,中文叫动态内存分配,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。
相关函数
callocreallocfree、_alloca
2函数声明
全名
void *malloc(size_t size);
备注
void* 表示未确定类型的指针,void *可以指向任何类型的数据,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者...)。
3与new的区别
从函数声明上可以看出。malloc 和 new 至少有两个不同:new 返回指定类型的指针,并且可以自动计算所需要大小。比如:
int *p;
p = new int;

//返回类型为int*
类型(整数型指针),分配大小为
sizeof(int);
或:
int* parr;
parr = newint[100];

//返回类型为 int*
类型(整数型指针),分配大小为
sizeof(int) * 100;
而 malloc 则必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针
int* p;
p = (int*) malloc(sizeof(int)*128);
//分配128个(可根据实际需要替换该数值)整型存储单元,
//并将这128个连续的整型存储单元的首地址存储到指针变量p中
double*pd=(double*) malloc(sizeof(double)*12);
//分配12个double型存储单元,
//并将首地址存储到指针变量pd中
第一:malloc 函数返回的是 void * 类型。对于C++,如果你写成:
p = malloc (sizeof(int));
则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。所以必须通过 (int *) 来将强制转换。而对于C,没有这个要求,但为了使C程序更方便的移植到C++中来,建议养成强制转换的习惯。
第二:函数的实参为 sizeof(int) ,用于指明一个整型数据需要的大小。如果你写成:
int* p = (int *) malloc (1);
代码也能通过编译,但事实上只分配了1个字节大小的内存空间,当你往里头存入一个整数,就会有3个字节无家可归,而直接“住进邻居家”!造成的结果是后面的内存中原有数据内容被改写。
在Linux中可以有这样:malloc(0),这是因为Linux中malloc有一个下限值16Bytes,注意malloc(-1)是禁止的;但是在某些系统中是不允许malloc(0)的。在规范的程序中我们有必要按照这样的格式去使用malloc及free
type *p;
if(NULL == (p = (type *)malloc(sizeof(type))))

/*请使用if来判断,这是有必要的*/
{
perror("error...");
exit(1);
}
... /*其它代码*/
free(p);
p = NULL; /*请加上这句*/
malloc 也可以达到 new [] 的效果,申请出一段连续的内存,方法无非是指定你所需要内存大小。
比如想分配100个int类型的空间:
int* p = (int*) malloc( sizeof(int) * 100 );

//分配可以放得下100个整数的内存空间。
另外有一点不能直接看出的区别是,malloc只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。
除了分配及最后释放的方法不一样以外,通过malloc或new得到指针,在其它操作上保持一致。
对其做一个特例补充
char*ptr;
if((ptr = (char*)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
此时得到的是Got a valid pointer。把0赋给malloc能得到一个合法的指针
4工作机制
malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
Linux Libc6采用的机制是在free的时候试图整合相邻的碎片,使其合并成为一个较大的free空间。
5程序示例
正常程序
typedefstructdata_type{
intage;
charname[20];
} data;
data *bob;
bob = (data *) malloc( sizeof(data) );
if( bob != NULL ) {
bob->age = 22;
strcpy( bob->name,"Robert");
printf( "%s is %dyears old\n", bob->name, bob->age );
}else{
printf("mallocerror!\n");
exit(1);
}
free( bob );
bob = NULL;
内存泄漏实例
例1:
#include <stdio.h>
#include <malloc.h>
#define MAX 100000000
intmain(void)
{
int*a[MAX];
inti;
for( i=0; i<MAX; i++) {
a[i]= (int*)malloc( MAX );
}
return0;
}
例2:
#include "stdio.h"
#include "malloc.h" //malloc()函数被包含在malloc.h里面
intmain(void) //
主函数程序的入口
{
char*a; //声明一个指向char的指针
a=(char*)malloc(100*sizeof(char));//使用malloc分配内存的首地址,然后赋值给a
gets(a); //从用户那里得到数据,把数据放入a中
printf("%s\n",a);//输出用户输入的数据
free(a); //释放掉使用的内存地址,就是因为可以释放内存地址才被称为动态内存分配
return0; //返回,退出
//例2有无内存泄露?
}

free函数
原型: void free(void *ptr)
功 能: 释放ptr指向的存储空间。被释放的空间通常被送入可用存储区池,以后可在调用malloc、realloc以及calloc函数来再分配。
程序例:
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
int main(void)
{
char *str;
/* allocate memory for string */
str = (char *)malloc(10);
if(str == NULL){
perror("malloc");
exit(1);
}
/* copy "Hello" to string */
strcpy(str, "Hello");
/* display string */
printf("String is %s\n", str);
/* free memory */
free(str);
return 0;
}
malloc和free函数详解
本文介绍malloc和free函数的内容。
在C中,对内存的管理是相当重要。下面开始介绍这两个函数:
1. malloc()和free()的基本概念以及基本用法:
1. 函数原型及说明:
void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。
关于分配失败的原因,应该有多种,比如说空间不足就是一种。
void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
2. 函数的用法:
其实这两个函数用起来倒不是很难,也就是malloc()之后觉得用够了就甩了它把它给free()了,举个简单例子:
程序代码:
// Code...
char *Ptr = NULL;
Ptr = (char *)malloc(100 * sizeof(char));
if (NULL == Ptr)
{
exit (1);
}
gets(Ptr);
// code...
free(Ptr);
Ptr = NULL;
/ code...
就是这样!当然,具体情况要具体分析以及具体解决。比如说,你定义了一个指针,在一个函数里申请了一块内存然后通过函数返回传递给这个指针,那么也许释放这块内存这项工作就应该留给其他函数了。
3. 关于函数使用需要注意的一些地方:
A. 申请了内存空间后,必须检查是否分配成功
B. 当不需要再使用申请的内存时,记得释放;释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。
C. 这两个函数应该是配对。如果申请后不释放就是内存泄露;如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上会出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。
D. 虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查。
现在进入第二部分:
2. malloc()到底从哪里得来了内存空间:
1. malloc()到底从哪里得到了内存空间?答案是从里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。关于堆的知识可以查询数据结构方面的知识或查询以前的一篇帖子C/C++堆、栈及静态数据区详解。这里不过多介绍。
2. 在使用malloc()分配内存空间后,一定要记得释放内存空间,否则就会出现内存泄漏。
3. free()到底释放了什么
free()释放的是指针指向的内存!注意!释放的是内存,不是指针!指针并没有被释放,指针仍然指向原来的存储空间。指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用了。
3. malloc()以及free()的机制:
事实上,仔细看一下free()的函数原型,也许也会发现似乎很神奇,free()函数非常简单,只有一个参数,只要把指向申请空间的指针传递给free()中的参数就可以完成释放工作!这里要追踪到malloc()的申请问题了。申请的时候实际上占用的内存要比申请的大。因为超出的空间是用来记录对这块内存的管理信息。
大多数实现所分配的存储空间比所要求的要稍大一些,额外的空间用来记录管理信息——分配块的长度,指向下一个分配块的指针等等。这就意味着如果写过一个已分配区的尾端,则会改写后一块的管理信息。这种类型的错误是灾难性的,但是因为这种错误不会很快就暴露出来,所以也就很难发现。将指向分配块的指针向后移动也可能会改写本块的管理信息。
malloc()申请的空间实际就是分了两个不同性质的空间。一个就是用来记录管理信息的空间,另外一个就是可用空间了。而用来记录管理信息的实际上是一个结构体。在C语言中,经常用结构来记录信息!下面看看这个结构体的原型:
程序代码:
struct mem_control_block {
int is_available; //一般来说应该是一个可用空间的首地址,但这里英文单词却显示出空间是否可用的一个标记
int size; //这是实际空间的大小
};
所以,free()就是根据这个结构体的信息来释放malloc()申请的空间!而结构体的两个成员的大小我想应该是操作系统的事了。
下面看看free()的源代码
// code...
void free(void *ptr)
{
struct mem_control_block *free;
free = ptr - sizeof(struct mem_control_block);
free->is_available = 1;
return;
}
至于malloc的源码,有兴趣的可以到网上找一下!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: