malloc函数
malloc函数的返回值为void*类型
内存管理函数操作的内存是在堆区空间
malloc函数使用示例
free(p)相当于值传递,不能改变p本身。
free只是释放了空间,释放后p依然指向原地址,故需要手动置NULL。
calloc函数
calloc可以指定开辟n个指定类型的空间,开辟后初始化开辟空间数据为0。
只有calloc开辟空间时会初始化空间。像malloc和realloc开辟空间后的数据为随机值。
realloc
若realloc开辟失败,原开辟空间位置找不到且原空间没有释放,故需要用另一个指针接收,
确认开辟成功后再将新空间的起始地址赋给p。且只有calloc会初始化空间,realloc和malloc不会初始化空间。
realloc函数的参数为NULL时,等价于malloc函数
动态分配的常见错误
1.对NULL指针的解引用操作
开辟空间有可能失败,如果不去判断malloc函数的返回值直接赋值,就有可以对NULL指针的解引用操作。
2.对动态开辟空间的越界访问
如果越界访问程序会崩溃
3.对非动态开辟内存使用free释放
上述代码问题1:如果对非动态开辟内存使用free释放,程序会崩溃
上述代码问题2:如果p的指向发生改变,则原开辟空间就找不到了,即出现内存泄漏问题。
动态开辟空间的释放
上述代码如果不用free主动释放,则直到程序结束,由操作系统回收。
4.用free释放部分空间
用free释放部分空间,程序会崩溃。
5.对同⼀块动态内存多次释放
如果连续free(p)两次,程序就会崩溃。
但free(p)一次后就将p置空指针则再次free(p)就不会报错,因为free(NULL)则free函数什么都不干。
6.动态开辟内存忘记释放(内存泄漏)
p是一个局部变量,函数结束之后就会将p销毁,就再也找不到开辟的空间了。
习题1
p是str的一份临时拷贝
修改方法(不考虑在GetMemory函数中开辟空间失败的情况)
方法1
申请完空间记得要释放空间(free(str); str = NULL;)
方法2
直接不要参数,直接返回一个指针。
习题2
GetMemory函数调用返回后(原空间被销毁),该函数的函数栈帧开辟空间将被printf函数开辟栈帧空间覆盖,故原p指向的空间为随机值。
简单例子(返回栈空间地址)
修改方法
习题3
运行后正常打印hello
上述代码存在的问题:
1.动态开辟的空间没有释放。
2.在GetMemory函数中开辟空间最好要判断一下是否开辟成功。
修改方法
习题4
原开辟空间使用完释放后没有将str置为空指针,此时str就是野指针,使用则造成非法访问
修改方法
free函数释放完空间后记得要将原来指针置为NULL。