说说动态内存分配

c/c++

浏览数:77

2019-3-30

当编写程序时,偶尔会不确定数组的大小(包括存储字符串的数组)。较为方便的做法是等到程序运行时再来确定数组的实际大小。
在标准C中,提供了3个库函数:malloc(),calloc()和realloc()。那么他们有什么区别,分别用在什么场合呢?

malloc()函数

函数原型:
void * malloc(size_t num_byte)
参数介绍:

  • 一般来说,如果申请成功会它返回一个无类型(通用)指针,使用者需要通过强制类型转换将其转换为你需要的类型。如果申请失败,函数返回空指针。
  • num_byte为你申请的空间大小,它固定以8位单字节为单位。在实际编程中,为了程序的可移植性,往往使用sizeof()运算符来计算申请的单个元素数据类型所占的字节大小。
int *p;
p = (int *)malloc( n * sizeof(int) );
if ( NULL == p ){
    printf("malloc failed!");
    exit(EXIT_FAILURE);
}
...
  • 需要注意的是,它从内存的堆(heap)资源中分配空间,且不会对分配的内存资源进行初始化。

calloc()函数

函数原型:
void *calloc(size_t n_memb,size_t size)
参数介绍:

  • 同malloc()函数,如果申请成功会它返回一个无类型(通用)指针,使用者需要通过强制类型转换将其转换为你需要的类型。如果申请失败,函数返回空指针。
  • n_memb为申请的元素个数,size为每个元素的所占字节大小。
  • 在分配了内存之后,会以对所有位清零的方式进行初始化。
  • 下例展示为n个整数的数组分配内存空间,并初始化数组元素为0。
int *a;
a = (int *)calloc( n, sizeof(int) );
if ( NULL == a ){
    printf("calloc failed!");
    exit(EXIT_FAILURE);
}
  • 通过调用以1为第一个实参的方式,可以为任何类型的数据项分配已初始化为零的空间。

realloc()函数

一旦分配完了空间,稍后可能会发现空间过小或者过大。此时该函数可以调整原来空间的大小以适应新的要求。
函数原型:
void *realloc(void *ptr, size_t size)
参数介绍:

  • ptr必须指向先前通过malloc()或calloc()或realloc()函数分配的空间指针。
  • size表示内存块的新尺寸,它可以大于或小于原尺寸。

使用原则:

  • 它不会对扩展的内存块进行初始化。
  • 如果分配失败,返回空指针,且原数据块不受影响。
  • 如果ptr设置为空指针,行为同malloc()函数。
  • 如果size设置为0,行为同free()函数,即释放ptr所指空间资源。
  • 在扩大空间的情况下,realloc()会尽量在原地进行扩充,如果无法原地扩充(内存块后面的空间已经用于其他目的),它会在别处重新分配内存块,并把旧块中的数据复制过去。所以,在调用完该函数后,切记更新所有指向该内存块的指针变量。

free()函数

在讲解了空间分配函数后,不得不提的就是要及时!及时!及时!释放之前申请的空间。否则随着程序的运行,会产生大量内存垃圾(内存泄露),最后系统会因资源耗尽而嗝屁。
函数原型:
void free(void *ptr)
参数介绍:

  • 使用它很容易,你只要把你之前申请的现在不需要的内存块指针传递给它就好了。
p = malloc(...);
...
free(p);
  • 虽然利用free()函数释放了p指向的内存空间,但p的值并没有改变。如果不把p及时及时及时指向空(NULL),会产生悬空指针,如果之后程序试图修改它指向的内存数据,会有程序崩溃等损失惨重的后果。