关于malloc,calloc,realloc函数不同解析

一、malloc
malloc在MSDN中原型为:
void *malloc( size_t size );
介绍为:
malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available. To return a pointer to a type other than void, use a type cast on the return value. The storage space pointed to by the return value is guaranteed to be suitably aligned for storage of any type of object. If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item. Always check the return from malloc, even if the amount of memory requested is small.

大概意思为:
malloc返回一个指针,如果没有成功分配内存或内存不够大导致分配失败,会返回NULL指针。否则返回分配内容的首地址。

在这里我要注意的是:如果给malloc中size写入0,会给变量写入0字节的大小。
这里就有歧义了。
如果我给程序写入这样一行代码:

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

p的值是不是NULL呢?
经VS2013检验,不是NULL,这是为什么呢?
在MSDN中有这么一段话:
The malloc function allocates a memory block of at least size bytes. The block may be larger than size bytes because of space required for alignment and maintenance information.

意思是,malloc生成的空间大小是要比你写入的空间大小要大的。
解释如下:
首先:
在标准的malloc实现中,并不检查输入值的大小,而是将输入值做对齐操作后直接从堆上分配空间。
其次:
不论输入值的大小为多少,在malloc的内部最小的内存分配大小是一个定值(一般是8B),因为malloc需要用这部分空间来维护堆上的内存块链表。所以当用户申请一块0B的空间时,malloc实际分配的空间是8B,如果用户申请的空间是X,则malloc实际分配的空间是(对齐(X) + 8)。这也是为什么malloc分配的空间千万不能越界使用的原因:堆的内部链表结构将被破坏。
关于malloc,calloc,realloc函数不同解析_第1张图片

那么,free是怎么知道要释放多少内存的呢?
看图~
malloc自动记录了此次分配的内存大小。

二、calloc
那calloc是用来干嘛的呢?
calloc在MSDN中描述如下:
calloc
Allocates an array in memory with elements initialized to 0.

void *calloc( size_t num, size_t size );

Routine Required Header Compatibility
calloc

int *p = (int*)calloc(0,2*sizeof(int));
//相当于
int *p=(int *)malloc(2*sizeof(int));
memset(p,0,2*sizeof(int));

那为什么日常中我们看到用malloc的多于calloc呢,是因为calloc虽然对内存空间进行了初始化,但是同时也降低了程序的效率。
而在一些情况下是不需要对内存空间进行初始化的~

三、realloc
ANSI C说明了三个用于存储空间动态分配的函数
(1) malloc 分配指定字节数的存储区。此存储区中的初始值不确定
(2) calloc 为指定长度的对象,分配能容纳其指定个数的存储空间。该空间中的每一位(bit)都初始化为0
(3) realloc 更改以前分配区的长度(增加或减少)。当增加长度时,可能需将以前分配区的内容移到另一个足够大的区域,而新增区域内的初始值则不确定
这是以上三个函数的区别

realloc分配失败时,返回NULL
realloc分配失败时,原来的内存空间不改变,不释放也不会移动
如果size=0,realloc = free,只对指针指向内存进行释放
对于二级指针来说,realloc(**p,0),只会释放一维指针,不会释放内存,所以要注意内存泄露
传递给realloc的指针必须是经过malloc,calloc,realloc申请的
当ptr为NULL,realloc(ptr,10) = malloc(ptr,10)

realloc使我们可以增、减以前分配区的长度(最常见的用法是增加该区)。
PS:在动态顺序表中就是用的realloc进行增容

如果先分配一个可容纳长度为512的数组的空间,并在运行时填充它,但又发现空间不够,则可调用realloc扩充该存储空间。

1.如果在该存储区后有足够的空间可供扩充,则可在原存储区位置上向高地址方向扩充,并返回传送给它的同样的指针值。

2.如果在原存储区后没有足够的空间,则realloc分配另一个足够大的存储区,将现存的5 1 2个元素数组的内容复制到新分配的存储区。

因为这种存储区可能会移动位置,所以不应当使用任何指针指在该区中。

注意,
realloc的最后一个参数是存储区的newsize(新长度),不是新、旧长度之差。
作为一个特例,若ptr是一个空指针,则realloc的功能与malloc相同,用于分配一个指定长度newsize的存储区。

四、alloca
alloca函数
还有一个函数也值得一提,这就是alloca。其调用序列与malloc相同,但是它是在当前函数的栈帧上分配存储空间,而不是在堆中。
其优点是:当 函数返回时,自动释放它所使用的栈帧,所以不必再为释放空间而费心。其缺点是:某些系统在函数已被调用后不能增加栈帧长度,于是也就不能支持alloca 函数。尽管如此,很多软件包还是使用alloca函数,也有很多系统支持它。
_alloca
Allocates memory on the stack.

void *_alloca( size_t size );

Routine Required Header Compatibility
_alloca

你可能感兴趣的:(函数,malloc)