malloc()/calloc()、realloc函数

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;


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值