11.2 malloc和free
C函数库提供了malloc和free两个函数,分别用于执行动态内存分配和释放。这些函数维护一个可用内存池。当一个程序另外需要一些内存时,它就调用malloc函数,malloc从内存池中提取一块合适的内存,并向该程序返回一个指向这块内存的指针。这块内存此时并没有以任何方式进行初始化。如果对这块内存初始化非常重要,你要么自己动手对它进行初始化,要么使用calloc函数。当一块以前分配的内存不再使用时,程序调用free函数把它归还给内存池供以后所需。
/*
** malloc和free。
*/
#include <stdio.h>
#include <stdlib.h>
int main( void ){
int *pm, *pm2, *pmt;
int *pc, *pc2, *pct;
int size;
size = 5;
/*
** allocate size * sizeof(int) bytes memory by using malloc function.
** the allocated memory doesn't be initialized.
*/
pm = (int *)malloc( size * sizeof(int) );
pmt = pm;
pm2 = pm + size;
printf( "print the elements by using malloc function:\n" );
while( pm < pm2 ){
printf( "%d ", *pm );
++pm;
}
printf( "\n" );
/*
** free dynamic memory.
*/
free( pmt );
/*
** allocate size * sizeof(int) bytes memory by using calloc function.
** the allocated memory can be initialized to zero.
*/
pc = (int *)calloc( size, sizeof(int) );
pct = pc;
pc2 = pc + size;
printf( "print the elements by using calloc function:\n" );
while( pc < pc2 ){
printf( "%d ", *pc );
++pc;
}
printf( "\n" );
/*
** free dynamic memory.
*/
free( pct );
return EXIT_SUCCESS;
}
/* 输出:

*/
这两个函数的原型如下所示,它们都在头文件stdlib.h中声明:
void *malloc( size_t size );
void free( void *pointer );
malloc的参数就是需要分配的内存字节(字符)数。如果内存池中的可用内存可以满足这个需求,malloc就返回一个指向被分配的内存块起始位置的指针。
malloc所分配的是一块连续的内存。同时,malloc实际分配的内存可能比请求的稍微多一点。但是,这个行为是有编译器定义的,所以不能指望它肯定会分配比请求更多的内存。
如果内存池是空的,或者它的可能内存无法满足请求,会发生什么情况呢?在这种情况下,malloc函数向操作系统请求,要求得到更多的内存,并在这块新内存上执行分配任务。如果操作系统无法向malloc提供更多的内存,malloc就返回一个NULL指针。因此,对每个malloc返回的指针都进行检查,确保它并非NULL,这非常重要。
/*
** malloc和free。
*/
#include <stdio.h>
#include <stdlib.h>
int main( void ){
int *pm;
int size, size2, size3;
size = 100;
/*
** allocate size * sizeof(int) bytes memory.
*/
pm = (int *)malloc( size * sizeof(int) );
size2 = sizeof(pm);
size3 = sizeof(*pm);
printf( "sizeof(pm) = %zd, sizeof(*pm) = %zd\n", size2, size3 );
/*
** test the memory allocation is successful or failing.
*/
if( pm != NULL ){
printf( "malloc function allocate %d bytes memory at least.\n", size * sizeof(int) );
} else{
printf( "memory allocation fails.\n" );
}
/*
** free dynamic memory.
*/
free( pm );
return EXIT_SUCCESS;
}
/* 输出:

*/
/*
** 测试系统最多能够分配多少内存空间给这个程序。
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main( void ){
long mb = pow( 2, 10 ) * pow( 2, 10 );
int counter = 0;
while( malloc(mb) ){
counter++;
}
printf( "The system can allocate %d MBs memory.\n", counter );
return EXIT_SUCCESS;
}
/* 输出:

*/
free的参数必须要么是NULL,要么是一个先前从malloc、calloc或realloc返回的值。向free传递一个NULL参数不会产生任何效果。
malloc又是如何知道所请求的内存需要存储的是整数、浮点值、结构还是数组呢?它并不知情---malloc返回一个类型为void*的指针,正是缘于这个原因。标准表示一个void*类型的指针可以转换为其他任何类型的指针。但是,有些编译器,尤其是那些老式的编译器,可能要求你在转换时使用强制类型转换。
对于要求边界对齐的机器,malloc所返回的内存的起始位置将始终能够满足对边界对齐要求最严格的类型的要求。