zoukankan      html  css  js  c++  java
  • malloc与free函数用法

    C里,内存管理是通过专门的函数来实现。另外,为了兼容各种编程语言,操作系统提供的接口通常是 C 语言写成的函数声明 Windows 本身也由C和汇编语言写成)。

    分配内存 malloc 函数

    需要包含头文件:

     #include <stdlib.h>  

    函数声明(函数原型)

    void *malloc(int size);

    说明:malloc 向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。

    从函数声明上可以看出。malloc  new 至少有两个不同new 返回指定类型的指针,并且可以自动计算所需要大小。比如:

    int *p;

    p = new int; //返回类型为int* 类型(整数型指针),分配大小为 sizeof(int);

    或: 

    int* parr;

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

     malloc 则必须由我们计算要字节数,并且在返回后强行转换为实际类型的指针。 

    int* p; 

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

    第一、malloc 函数返回的是 void * 类型,如果你写成:p = malloc (sizeof(int)); 则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。所以必须通过 (int *) 来将强制转换。

    第二、函数的实参为 sizeof(int) ,用于指明一个整型数据需要的大小。如果你写成: 

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

    代码也能通过编译,但事实上只分配了1个字节大小的内存空间,当你往里头存入一个整数,就会有3个字节无家可归,而直接“住进邻居家”!造成的结果是后面的内存中原有数据内容全部被清空。

    malloc 也可以达到 new [] 的效果,申请出一段连续的内存,方法无非是指定你所需要内存大小。

    比如想分配100int类型的空间:

    int* p = (int *) malloc ( sizeof(int) * 100 ); //分配可以放得下100个整数的内存空间。

    另外有一点不能直接看出的区别是,malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。

    除了分配及最后释放的方法不一样以外,通过mallocnew得到指针,在其它操作上保持一致。

     

    释放内存 free 函数

    需要包含头文件( malloc 一样)

    函数声明:

    void free(void *block);

    即: void free(指针变量)

    之所以把形参中的指针声明为 void* ,是因为free必须可以释放任意类型的指针,而任意类型的指针都可以转换为void *

    举例:

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

    *p = 100;

    free(p); //释放 p 所指的内存空间

    或者:

    int* p = (int *) malloc ( sizeof(int) * 100 ); //分配可以放得下100个整数的内存空间。

    ……

    free(p);

    free 不管你的指针指向多大的空间,均可以正确地进行释放,这一点释放比 delete/delete [] 要方便。不过,必须注意,如果你在分配指针时,用的是newnew[],那么抱歉,当你在释放内存时,你并不能图方便而使用free来释放。反过来,你用malloc 分配的内存,也不能用delete/delete[] 来释放。一句话,new/deletenew[]/delete[]malloc/free 三对均需配套使用,不可混用!

     

    3.calloc()realloc()

    calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小:void *calloc(size_t numElements,size_t sizeOfElement); 

    如果调用成功,函数malloc()和函数calloc()都将返回所分配的内存空间的首地址。函数malloc()和函数calloc()的主要区别是前者不能初始化所分配的内存空间,而后者能。如果由malloc()函数分配的内存空间原来没有被使用过,则其中的每一位可能都是0;反之,如果这部分内存曾经被分配过,则其中可能遗留有各种各样的数据。也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常进行,但经过一段时间(内存空间还已经被重新分配)可能会出现问题。

    函数calloc()会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那麽这些元素将保证会被初始化为0;如果你是为指针类型的元素分配内存,那麽这些元素通常会被初始化为空指针;如果你为实型数据分配内存,则这些元素会被初始化为浮点型的零。

     

    realloc()

    原型:extern void *realloc(void *mem_address, unsigned int newsize);

    用法:#include 有些编译器需要#include

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

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

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

      注意:这里原始内存中的数据还是保持不变的。

      举例:

      // realloc.c

      #include

      #include

      main()

      {

      char *p;

      clrscr(); // clear screen

      p=(char *)malloc(100);

      if(p)

      printf("Memory Allocated at: %x",p);

      else

      printf("Not Enough Memory! ");

      getchar();

      p=(char *)realloc(p,256);

      if(p)

      printf("Memory Reallocated at: %x",p);

      else

      printf("Not Enough Memory! ");

      free(p);

      getchar();

      return 0;

      }

      详细说明及注意要点:

      1、如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address

    这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。那么就ok。得到的是一块连续的内存。

      2、如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存, 并把原来大小内存空间中的内容复制到newsize中,返回新的mem_address指针(数据被移动了), 老块被放回堆上。

      例如:

      #include

      char *p*q;

      p = (char * ) malloc (10);

      q=p;

      p = (char * ) realloc (p,20);

      …………………………

      这段程序也许在编译器中没有办法通过,因为编译器可能会为我们消除一些隐患!在这里我们只是增加了一个记录原来内存地址的指针q,然后记录了原来的内存地址p,如果不幸的话,数据发生了移动,那么所记录的原来的内存地址q所指向的内存空间实际上已经放回到堆上了!这样一来,我们应该终于意识到问题的所在和可怕了吧!

      3、返回情况

      返回的是一个void类型的指针,调用成功。(这就再你需要的时候进行强制类型转换)

      返回NULL,当需要扩展的大小(第二个参数)为0并且第一个参数不为NULL,此时原内存变成了“freed(游离)”的了。

      返回NULL,当没有足够的空间可供扩展的时候,此时,原内存空间的大小维持不变。

      4、特殊情况

      如果mem_addressnull,则realloc()malloc()类似。分配一个newsize的内存块,返回一个指向该内存块的指针。

      如果newsize大小为0,那么释放mem_address指向的内存,并返回null

      如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回null.而原来的内存块保持不变。

  • 相关阅读:
    JavaScript模态对话框类
    事件模块的演变(1)
    html5中可通过document.head获取head元素
    How to search for just a specific file type in Visual Studio code?
    What do 'lazy' and 'greedy' mean in the context of regular expressions?
    正则非获取匹配 Lookahead and Lookbehind ZeroLength Assertions
    regex length 正则长度问题
    Inversion of Control vs Dependency Injection
    How to return View with QueryString in ASP.NET MVC 2?
    今天才发现Google Reader
  • 原文地址:https://www.cnblogs.com/King-Gentleman/p/5528634.html
Copyright © 2011-2022 走看看