动态内存分配

为什么使用动态内存分配

对于传统数组,会遇到这样的问题:

int arr[5] ;

对这个数组我们在定义的时候必须给提前开辟好空间,并且在程序执行的过程中,这个开辟的内存空间是一直存在的,除非等到这个函数执行完毕,才会将空间释放。还有一个问题就是这个数组在程序中无法被修改。 这些问题给我们造成了一些使用上的不方便,所以,C中具有动态内存分配的机制。 

 malloc()函数和free()函数 

void *malloc(size_t size)

malloc会从内存池里提取一块合适的内存(连续的),并返回指向这块内存(起始位置的指针,该指针的类型为void*指针标准表示一个void*类型的指针可以转换成其它任何类型的指针,但有些编译器需要使用强制类型转换。malloc分配的这块内存并没有初始化。

如果内存池是空的,或者它的可用内存无法满足你的要求,这是malloc函数会向操作系统请求,要求得到更多的内存,并在这块内存上执行分配任务,如果操作系统无法向malloc提供更多的内存,则malloc返回NULL。因此对malloc返回值必须加以检查,确定不是NULL。

void free(void *pointer);

free的参数要么是NULL,要么是一个先前从malloc、calloc或者realloc中返回的值,向free传递NULL不会产生任何效果。

free(p);之后, p所指的内存空间是归还了,但是p的值并没有变,因为从free的函数接口来看根本就没法改变p的值, p现在指向的内存空间已经不属于用户,换句话说, p成了野指针,为避免出现野指针,我们应该在free(p);之后手动置p = NULL;

 calloc()函数和realloc()函数

另外还有两个内存分配函数:calloc和realloc,定义如下:

void *calloc(size_t num_elements,size_t element_size);
void *realloc(void*ptr,size_t new_size);

calloc也用于分配内存,它与malloc的区别在于,它在返回指向内存的指针之前把它初始化为0。另外,calloc的参数包含了所需元素的数量和每个元素的字节数,根据这些值,它能够计算出总共需要分配的内存。

realloc函数用于修改一个原先已经分配的内存块的大小,使用这个函数,可以使一块内存扩大或者缩小,如果它用于扩大内存,那么这块内存原先的内容依旧保留,新增加的内存将添加到原来内存块的后面,新内存并未以任何方式进行初始化,如果它用于缩小内存块,该内存块尾巴的部分将被拿掉,剩余的部分保留原先的内容。如果原先的内存块大小无法改变,则realloc将重新分配一个正确大小的内存,并把原先内存块中的内容复制到新的内存块中,因此使用realloc后,你就不能在使用指向旧内存的指针,而是应该使用realloc返回的指针。最后,若是realloc的第一个参数为NULL,那么它的作用就和malloc一样。

常见的动态内存分配错误

常见的错误类型有:对NULL指针进行解引用,对分配内存进行操作时越界,释放并非动态分配的内存,试图释放一块动态内存的一部分,释放动态内存之后继续使用。

内存泄漏

程序退出时整个进程地址空间都会释放 。但是当动态内存不需要再使用时,它应该被释放。这样它以后可以被重新分配使用,分配内存但在使用完毕之后不释放,将引起内存泄漏。在那些共用一个通用内存池的操作系统中,内存泄漏将一点点地榨干内存。退出程序。

posted @ 2018-02-26 14:49  刘-皇叔  阅读(235)  评论(0)    收藏  举报