malloc()/calloc()、realloc函数

来源:互联网 发布:linux echo e 编辑:程序博客网 时间:2024/05/01 18:21

C语言跟内存分配方式

(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3)从堆上分配,亦称动态内存分配。程序在运行的时候用mallocnew申请任意多少的内存,程序员自己负责在何时用freedelete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等。

(1) alloc()

向栈申请内存,因此无需释放.

(2)malloc()/calloc()

分配的内存是位于堆中的,并且没有初始化内存的内容,因此基本上malloc之后,调用函数memset来初始化这部分的内存空间.

calloc则将初始化这部分的内存,设置为0.申请的内存最终需要通过函数free来释放.sbrk则是增加数据段的大小;malloc/calloc/free基本上都是C函数库实现的,OS无关.C函数库内部通过一定的结构来保存当前有多少可用内存.如果程序malloc的大小超出了库里所留存的空间,那么将首先调用brk系统调用来增加可用空间,然后再分配空间.free,释放的内存并不立即返回给os,而是保留在内部结构中.可以打个比方: brk类似于批发,一次性的向OS申请大的内存,malloc等函数则类似于零售,满足程序运行时的要求.这套机制类似于缓冲.使用这套机制的原因:系统调用不能支持任意大小的内存分配(有的系统调用只支持固定大小以及其倍数的内存申请,这样的话,对于小内存的分配会造成浪费;系统调用申请内存代价昂贵,涉及到用户态和核心态的转换.

函数malloc()calloc()都可以用来分配动态内存空间,但两者稍有区别。

malloc()函数有一个参数,即要分配的内存空间的大小: void*malloc(size_t size);

calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就

是要分配的内存空间的大小: void *calloc(size_t numElementssize_t sizeOfElement)

如果调用成功,函数malloc()calloc()都将返回所分配的内存空间的首地址。

总之,当你在calloc()函数和malloc()函数之间作选择时,你只需考虑是否要初始化所分配的内存空间,而不用考虑函数是否能返回一个数组。

当程序运行过程中malloc,但是没有free的话,会造成内存泄漏.一部分的内存没有被使用,但是由于没有free,因此系统认为这部分内存还在使用,造成不断的向系统申请内存,是的系统可用内存不断减少.但是,内存泄漏仅仅指程序在运行时,程序退出时,OS将回收所有的资源.因此,适当的重起一下程序,有时候还是有点作用.

(3)realloc函数

realloc则只对malloc申请的内存进行大小的调整.

1.原型:

extern void*realloc(void *ptr, size_t newsize);

 用法:#include <stdlib.h>

 功能:改变ptr所指内存区域的大小为newsize长度。

 说明:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL

       当内存不再使用时,应使用free()函数将内存块释放。

它用来在堆中更改已经配置好的内存空间。第一个参数为试图更改大小的原堆空间的位置,newsize为新的内存大小。

2.减小内存:

realloc()仅仅更改索引信息,但并不代表被减少的部分还可以访问,减少部分的内存将交给操作系统管理。

3.增大内存:

(1)如果当前内存段后面拥有需要的内存空间,则直接扩展这段内存空间,realloc()将返回原来指针。

(2)如果当前内存段后面的空闲字节不够,那么就使用堆中第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据块释放掉,返回新内存块位置。

(3)如果申请失败,将返回NULL,此时原来指针仍然有效。

为了防止原来指针仍然有效,一般不使用如下语句:ptr = realloc(ptr, new_amount);

 

#include <stdio.h>#include <stdlib.h>int main(int argc, char **argv){    char *p;    p = (char *)malloc(100);    if(p)        printf("Memory Allocated at:%p\n", p);    else        printf("Not Enough Memory!\n");    p = (char *)realloc(p, 256);    if(p)        printf("Memory Reallocated at:%p\n", p);    else        printf("Not Enough Memory!\n");    free(p);    return 0;}


通常,realloc的用法会如下

p = realloc(p, new_size);if (p == NULL) {        return;}


如果realloc()失败,ptr指向的这块内存不会变化,不会free或者移动。也就是说,如果realloc()失败了,照着上面代码的写法,这块内存就被永远遗忘了。

tmp = realloc(p, new_size);if (tmp == NULL) {        free(p);        return;}p = tmp;


 

原创粉丝点击