在C语言中,内存管理是很重要的,最近刷算法题目也用到了malloc和free函数,在此记录一下;
一、函数原型及说明:
malloc():
函数原型:
1 | void *malloc(long NumBytes); |
该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。
关于分配失败的原因,应该有多种,比如说空间不足就是一种。
free():
函数原型:
1 | void free(void *FirstByte); |
该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
二、函数使用注意事项:
1、申请了内存空间后,必须检查是否分配成功;
2、当不需要再使用申请的内存时,记得释放;
释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。
3、这两个函数应该是配对使用;
如果申请后不释放就是内存泄露;如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上会出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。
4、虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查;
三、具体例子:
1 | // Code... |
四、原理部分:
1、malloc内存空间的来源:
答案是从堆里面获得空间。
也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。
在使用malloc()分配内存空间后,一定要记得释放内存空间,否则就会出现内存泄漏。
2、free释放了什么:
free()释放的是指针指向的内存。
注意!释放的是内存,不是指针!指针并没有被释放,指针仍然指向原来的存储空间。指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用了。
free() 不会改变 指针变量本身的值,调用 free() 后它仍然会指向相同的内存空间,但是此时该内存已无效,不能被使用。所以建议将 指针的值设置为 NULL,例如:
1
2 free(ptr);
ptr = NULL;
free()的源代码:
1 | struct mem_control_block { |
五、直接定义一个数组和使用malloc动态分配的区别:
malloc作为一个包含在
头文件下的函数,用于申请空间。
我们平常定义数组一般习惯性的就直接定义,比如int a[5],此处就是直接定义了一个数组,数组内的元素都是int型,并且有五个,从一开始就确定了数组a的大小,并且无法被改变。
并且变量被存放在栈区,栈区的变量都是由系统自己开辟空间存储,并自动销毁空间释放的。
其实,还有一种定义数组的方式,那就是借助人为申请空间的方式定义一个数组。请看如下程序:
1 |
|
定义的方法是首先得定义一个指针,然后在这个指针的指向下,利用malloc去开辟一个自定义大小的空间。
此方法定义的数组变量被存放在堆区,是由用户自己开辟和释放的。
下面来看结果运行结果:

可见结果是理想无误的。
使用这种先定义指针后开辟空间的方式可以适用于一些开始并不知道数组空间大小的场景。
六、一个思维导图:
参考链接:链接
