关于c++指针的deIete理解及内存泄露原理
附∶①函数内的指针是局部变量,由编译器分配栈区空间(由cout<<&p可知p指针有空间地址,占用size字节长度由编译器类型决定),函数结束时自动释放空间。
②用new运算符等操作分配给指针的堆区空间(如:int*p=new int [n])只能人为分配(new等),并用指针协助分配(只能人为,只能用指针),并且不会自动释放,需要用deIete运算符等人为释放空间。
③已定义的变量名(如int n中的n)对应的地址再次编译都会改变(包括指针变量p地址及指针对应的堆区空间地址都如此,之所以对应的堆区空间地址也改变是因为再次编译后指针p的空间地址改变,编译到new运算符处时又给p赋一个新的堆区地址),可运行后输出地址后发现(这与内存泄露有关)
正文开始:
为什么delete []p后要给指针p赋成NULL?
首先我们要知道deIete []p的原理:delete的作用是更换p空间中存的地址值(把对应的堆区地址值换为另一个地址(栈区地址?),以此来切断两个空间的联系,并非删去两个空间,这个也叫释放堆区内存。之后,p中仍有地址,变成了野指针,会对接下来写的代码有危害,而赋NULL之后,p中地址值更换为0,这样就不会对下面代码有影响了。
所以delete后要赋NULL
内存泄露是什么?
一般内存泄露是堆区内存泄露,堆区要人为分配,释放,很可能忘记释放而造成泄露;栈区内存由编译器管理不会泄露。
若编译时相应代码中没有"delete []p",第二次编译之前才加上"deIete []p",之后不会出内存泄露,但第一次编译内存还是泄露了的。
第一次编译后指针自身内存空间已释放(释放是解除指针名与分配给它的空间地址联系),但它的自身内存空间中存储的堆区空间地址没有更换,即堆区空间地址没有被释放。
下图,在函数m()return编译后p的指针变量已被释放,p释放的自己的栈区地址最后给了主函数中二级指针变量,然后cout之前的这个指针地址和地址中的堆区空间地址值,可发现,这个指针变量虽然释放了空间,空间中的已分配的堆区地址值却没有更改,也就是说,这个堆区地址空间没有被释放,造成了内存泄露。