zoukankan      html  css  js  c++  java
  • C内存分配函数

    C语言跟内存分配方式
    (1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
    (2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
    (3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
      
    C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等。
      其中alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且没有初始化内存的内容,因此基本上malloc之后,调用函数memset来初始化这部分的内存空间。calloc则将初始化这部分的内存,设置为0. 而realloc则对malloc申请的内存进行大小的调整.申请的内存最终需要通过函数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 numElements,size_t sizeOfElement);如果调用成功,函数malloc()和calloc()都将返回所分配的内存空间的首地址。
      malloc()函数和calloc()函数的主要区别是前者不能初始化所分配的内存空间,而后者能。如果由malloc()函数分配的内存空间原来没有被使用过,则其中的每一位可能都是0;反之,如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题。
      calloc() 函数会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那么这些元素将保证会被初始化为零;如果你是为指针类型的元素分配内存,那么这些元素通常(但无法保证)会被初始化为空指针;如果你是为实数类型的元素分配内存,那么这些元素可能(只在某些计算机 中)会被初始化为浮点型的零。
      malloc() 函数和calloc()函数的另一点区别是calloc()函数会返回一个由某种对象组成的数组,但malloc()函数只返回一个对象。为了明确是为一个数组分配内存空间,有些程序员会选用calloc()函数。但是,除了是否初始化所分配的内存空间这一点之外,绝大多数程序员认为以下两种函数调用方式没有区别:
      calloc(numElements ,sizeOfElement);
      malloc(numElements *sizeOfElement) ;
      需要解释的一点是,理论上(按照ANSIC标准)指针的算术运算只能在一个指定的数组中进行,但是在实践中,即使C编译程序或翻译器遵循这种规定,许多C 程序还是冲破了这种限制。因此,尽管malloc()函数并不能返回一个数组,它所分配的内存空间仍然能供一个数组使用(对realloc()函数来说同样如此,尽管它也不能返回一个数组)。
      总之,当你在calloc()函数和malloc()函数之间作选择时,你只需考虑是否要初始化所分配的内存空间,而不用考虑函数是否能返回一个数组。
      当程序运行过程中malloc了,但是没有free的话,会造成内存泄漏.一部分的内存没有被使用,但是由于没有free,因此系统认为这部分内存还在使用,造成不断的向系统申请内存,是的系统可用内存不断减少.但是,内存泄漏仅仅指程序在运行时,程序退出时,OS将回收所有的资源.因此,适当的重起一下程序,有时候还是有点作用。

    函数realloc
    原型:extern void *realloc(void *mem_address, unsigned int newsize);  
    语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。//新的大小一定要大于原来的大小不然的话会导致数据丢失!   
    头文件:#include <stdlib.h> 有些编译器需要#include <alloc.h>,在TC2.0中可以使用alloc.h头文件   
    功能:先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。   
    返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。    
    注意:这里原始内存中的数据还是保持不变的。当内存不再使用时,应使用free()函数将内存块释放。   
    相关函数: malloc、calloc、free、_alloca
    真正认识realloc的工作方式:
    realloc用过很多次了。无非就是将已经存在的一块内存扩大。
    char* p = malloc(1024);
    char* q = realloc(p,2048);
    现在的问题是我们应该如何处理指针 p。 刚开始按照我最直观的理解,如果就是直接将 p = NULL;。 到最后只需要释放 q的空间就可以了。因为最近在做个封装。结果在做单元测试的时候发现。有时候我在 free(q); 的时候会出错。这样我就郁闷了。后来仔细一跟踪,发现 realloc 完以后 q 和 p 的指针地址是一样。不过有时候又不一样。

    仔细查了下资料。得到如下信息:
    1.如果当前连续内存块足够 realloc 的话,只是将p所指向的空间扩大,并返回p的指针地址。 这个时候 q 和 p 指向的地址是一样的。
    2.如果 当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p指向的内容 copy到 q,返回 q。并将p所指向的内存空间删除。
    这样也就是说 realloc 有时候会产生一个新的内存地址 有的时候不会。所以在分配完成后。我们需要判断下 p 是否等于 q。并做相应的处理。这里有点要注意的是要避免 p = realloc(p,2048); 这种写法。有可能会造成 realloc 分配失败后,p原先所指向的内存地址丢失。

    realloc使用总结:
    1.realloc失败的时候,返回NULL;
    2.realloc失败的时候,原来的内存不改变,不会释放也不会移动;
    3.假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址;
    4.如果size为0,效果等同于free();
    5.传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的;
    6.传递给realloc的指针可以为空,等同于malloc。

    包含头文件:#include <stdlib.h>

  • 相关阅读:
    [IOI1998] Pictures
    【C++】位操作(3)-获取某位的值
    PAT A 1013. Battle Over Cities (25)【并查集】
    hihoCoder 1391 Countries【预处理+排序+优先队列】2016北京网络赛
    PAT A 1014. Waiting in Line (30)【队列模拟】
    codeforces Round#379 div.2
    PAT A 1004. Counting Leaves (30)【vector+dfs】
    POJ 1163:The Triangle
    LeetCode39/40/22/77/17/401/78/51/46/47/79 11道回溯题(Backtracking)
    BZOJ 3680 吊打XXX
  • 原文地址:https://www.cnblogs.com/defias/p/3366717.html
Copyright © 2011-2022 走看看