动态内存分配
⭐关联知识点:linux动态内存分配
为什么使用动态内存分配
声明数组必须用一个编译时常量指定数组的长度。但是,数组的长度常常在运行时才知道,由于它所需要的内存空间取决于输入数据。
malloc和 free
malloc 和 free,分别用于执行动态内存分配和释放。这些函数维护一个可用内存池。当一个程序另外需要一些内存时,它就调用malloc 函数,malloc 从内存池中提取一块合适的内存,并向该程序返回一个指向这块内存的指针。这块内存此时并没有以任何方式进行初始化。如果对这块内存进行初始化非常重要,你要么自已动手对它进行初始化,要么使用 calloc函数。当一块以前分配的内存不再使用时,程序调用 free 函数把它归还给内存池供以后之需。
void *malloc( size_t size);
void free( void *pointer );
malloc的参数就是需要分配的内存字节数。如果内存池中的可用内存可以满足这个需求,malloc 就返回一个指向被分配的内存块起始位置的指针(void *),一个 void *类型的指针可以转换为其他任何类型的指针。
如果内存池是空的,或者内存不足,malloc函数(brk或者mmap)向操作系统请求,要求得到更多的内存,并在这块新内存上执行分配任务。如果操作系统无法向 malloc 提供更多的内存,malloc 就返回一个NULL指针。对每个从 malloc返回的指针检查,确保非NULL。
malloc所分配的是一块连续的内存(逻辑地址连续),对于要求边界对齐的机器,malloc所返回的内存的起始位置将满足对边界对齐要求的要求。
free的参数要么是NULL,要么是一个malloc、calloc或 realloc返回的值。向 free 传递一个NULL 参数不会产生任何效果。
calloc和 realloc
void *calloc( size_t num_elements,size_t element_size);
void realloc( void *ptr, size_t new_size);
- calloc也用于分配内存。
- malloc和 calloc之间的主要区别是calloc在返回指向内存的指针之前把申请的内存初始化为0。这个初始化常常能带来方便,但如果程序只把一些值存储到数组中,那么这个初始化纯属浪费时间。
- calloc 和 malloc 之间另一个小区别是请求内存数量的方式不同。calloc 的参数包括所需元素的数量和每个元素的字节数,然后计算出总共需要分配的内存。
realloc 修改一个原先已经分配的内存块的大小,可以使一块内存扩大或缩小。
(1)如果它用于扩大一个内存块,那么这块内存原先的内容依然保留,新增加的内存添加到原先内存块的后面,新内存并未以任何方法进行初始化。
(2)如果它用于缩小一个内存块,该内存块尾部的部分内存便被拿掉,剩余部分内存的原先内容依然保留。
(3)如果原先的内存块无法改变大小,realloc将分配另一块正确大小的内存,并把原先那块内存的内容复制到新的块上,返回一个新指针。
(4)如果realloc函数的第1个参数是NULL,那么它的行为就和 malloc一模一样。
使用动态分配的内存
int *pi;
pi = malloc( 25* sizeof( int ));//申请25个整数
int &pi2 = pi;
for(i= 0;i< 25;i+= 1)
*pi2++ = 0;//使用指针访问动态数组
//pi[i]=0;//使用下标访问动态数组
常见的动态内存错误
常见动态内存错误包括忘记检查所请求的内存是否成功分配对NULL指针解引用,操作、对分配的内存进行操作时越过边界、释放并非动态分配的内存、试图释放一块动态分配的内存的一部分以及一块动态内存被释放之后被继续使用。
可以封装一个函数来防止对NULL指针进行解引用。
void * alloc( size_t size ){
void *new_mem;
/*请求所需的内存,并检查确实分配成功*/
new_mem=malloc( size);
if(new_mem==NULL){
printf( "Out of memory!\n");
exit(1);
}
return new_mem;
}
内存泄漏
分配内存但在使用完毕后不释放将引起内存泄漏(memory leak)。在那些所有执行程序共享一个通用内存池的操作系统中,内存泄漏将一点点地榨干可用内存,最终使其一无所有。要摆脱这个困境,只有重启系统。
标签:malloc,realloc,void,free,内存,calloc,指针,size From: https://blog.51cto.com/u_16969274/12054969