C和指针之动态内存分配

1、为什么使用动态分配内存
  当不确定需要的内存空间的大小的时候,使用动态分配内存的方式去分配一块内存,这样不会对内存进行浪费。
 
2、动态分配内存的函数
  C函数库提供了三个动态分配内存的函数:malloc、calloc、realloc,这三个函数都能进行动态的内存分配。当这些内存不再使用时可以用free函数把这些内存归还给内存池,以达到内存释放的目的。
四个函数的函数原型如下:
void *malloc(size_t size);
void *calloc(size_t num_elements, size_t element_size);
void realloc(void *ptr, size_t new_size);
void free(void *pointer);
 
  malloc函数的参数就是需要分配的内存字节数。如果内存池中的可用内存可以满足这个需求,malloc就会返回一个指向被分配的内存块起始位置的指针。malloc所分配的内存是一块连续的地址,并不会分开位于两块或多块不同的内存。如果内存池是空的,或者它的可用内存无法满足申请的需求,此时malloc会向操作系统请求得到更多的内存,并在这块新的内存上执行分配任务。如果操作系统无法向malloc提供更多的内存,就会导致malloc分配内存失败,此时malloc会返回一个NULL指针。因此,对每个从malloc返回的指针都要进行检查,确保它并非NULL是非常重要的。malloc函数的返回值类型为void *型指针,可以将这个指针转换为申请所需要的任何类型的指针,可以满足任何类型的数据存储。
  calloc函数也可以用来分配内存。它与malloc之间的区别在于它在返回指向内存的指针之前把它初始化为了0。这带来了很大的方便,不过有时只需要存储数据,初始化就有点浪费时间了。他们二者之间还有一个区别就是请求内存数量的方式不同,calloc的参数包括所需要的元素的数量和每个元素的字节数,由此来计算总共需要分配的字节数。
  realloc函数用于修改一个原先已经分配的内存块的大小。也就是说realloc函数可以将一块内存增大或着缩小。如果使用realloc函数扩大一块内存块,那么这块内存块原先的内容将被保留下来,新增的内存添加到原先内存块的后面,新增的内存并未以任何方法进行初始化。如果使用realloc函数来进行内存缩小,该内存块的尾部将会被拿掉,剩余部分内存的原先内容依然保留。如果原先的内存块无法改变大小,realloc将分配另一块正确大小的内存,并把原先那块内存的内容复制到新的块上,因此在使用realloc函数之后,就不能再使用指向旧的内存的指针,而是应该改用realloc最新返回的指针。如果realloc函数的第一个参数是NULL,那么它的行为就和malloc一模一样。
  free函数的参数要么是NULL的指针,要么是先前从malloc、calloc、realloc返回的值,向free函数传递一个NULL的参数不会产生任何效果。
 
3、使用动态分配的内存
  在使用malloc函数分配的内存时,一定记得判断申请的内存是否为NULL,符号NULL定义于stdio.h,它实际上时字面值常量0,在这里起着视觉提醒器的作用,提醒我们返回的值是一个指针而不是整数。
  如果malloc函数内存分配成功,我们就拥有了一个size个字节的指针,这个size最好不要是某一个固定大小的值,一般使用如number*sizeof(int)等的动态计算大小的值来进行内存分配。
 
4、常见的动态内存的错误
  在使用动态内存分配的程序中,常常会出现许多错误。这些错误包括对NULL指针进行解引用操作、对分配的内存进行操作时越过边界、释放并非动态分配的内存、试图释放一块动态分配的内存的一部分以及一块内存被释放之后还继续使用它。
  动态分配内存最常见的错误是忘记检查所请求的内存是否分配成功,也就是判断返回的指针是否为NULL。第二个错误是在操作内存时超出了分配内存的边界,也就是申请了25个字节的内存,只能操作下标大于0或小于24的内存。操作超出部分的指针有时会引起严重的后果,例如被访问的内存保存了其他有用的值,而此时正好指针越界对其他数据进行了修改,将会改变其他地址上的数据,这是一个很严重的错误,并且不容易被发现。
  当使用free函数时也可能会出现错误。传递给free的指针必须是一个从malloc、calloc或realloc返回的指针。如果让free函数释放一块并非动态申请的内存时可能会导致程序立即终止或着在晚些时候终止,试图释放一块内存的一部分也有可能引起类似的问题。并且还要注意不要使用一块已经被free函数释放过的内存。
 
5、内存泄露
  当动态分配的内存不再需要是,应该被立即释放掉,这样它以后还可以被重新分配使用。分配的内存如果在使用完后不释放将会引起内存泄露(memory leak)。
  防止内存泄露的方法是使用一个动态申请内存的函数,并且该内存在使用完后就要使用free函数进行内存释放。
 
6、警告
检查malloc函数返回的指针是否为NULL
不允许访问动态分配的内存之外的区域
不能向free函数传递一个由非malloc函数返回的指针
不能在动态内存被释放之后再去访问它
 
 
 
原文地址:https://www.cnblogs.com/Jummyer/p/9852822.html