为什么说内存泄露是个大麻烦?
本人在校大学生,接触的东西不是很多,看见很多人在讨论内存泄露的事情,想起老师说的话:一个new配一个delete,一个malloc配一个free就行了,就觉得很奇怪。难道说遵从以上规则编写程序,还会存在内存泄露吗?求指教!
[解决办法]
等你写的程序大一点,要多人合作时,你要能遵从得了才叫碰鬼了呢。
[解决办法]
关键是有的时候在一个模块中new,需要在其它的模块中delete
或者有的时候由于程序运行逻辑的问题,delete的那部分程序没有被执行
除了new/delete,GDI资源等等也会造成内存泄露
在pc上还好,如果是在wince嵌入式操作系统上
内存本来就很小,总共就几十M,除去系统占用的,没剩多少了
如果你的app存在泄露的话,会运行的越来越慢,甚至卡死
[解决办法]
等你写的程序大一点,要多人合作时,你要能遵从得了才叫碰鬼了呢。
[解决办法]
有些内存泄露十分隐蔽,所以很烦人。
[解决办法]
根指针相关的内存泄露有很多种,不一定都是因为new/delete不匹配造成的,你们老师那样说是因为其接触实际代码量还不够多的缘故。
最常见的内存泄露出现在结构或类赋值,导致孤指针存在,使内存无法释放,例如:
struct T{
A *dat;
int n;};
T a={new A,20},b={0,0}; a=b; //--内存泄露了
char *s1="...",*s2= new char[256]; s2=s1; //-- 内存泄露了
char *s1=new char[40], *s2=new char[80]; strcpy(s1,s2) //- 内存超界泄露了
char *s1=new char[40],*s2="dfek dkr l kre";memset(s1,0x3c,40);strcat(s1,s2);//-内存超界泄露了
[解决办法]
内存泄漏会因为减少可用内存的数量从而降低计算机的性能。最终,在最糟糕的情况下,过多的可用内存被分配掉导致全部或部分设备停止正常工作,或者应用程序崩溃。
内存泄漏可能不严重,甚至能够被常规的手段检测出来。在现代操作系统中,一个应用程序使用的常规内存在程序终止时被释放。这表示一个短暂运行的应用程序中的内存泄漏不会导致严重后果。
在以下情况,内存泄漏导致较严重的后果:
* 程序运行后置之不理,并且随着时间的流失消耗越来越多的内存(比如服务器上的后台任务,尤其是嵌入式系统中的后台任务,这些任务可能被运行后很多年内都置之不理)
* 新的内存被频繁地分配,比如当显示电脑游戏或动画视频画面时
* 程序能够请求未被释放的内存(比如共享内存),甚至是在程序终止的时候
* 泄漏在操作系统内部发生
* 泄漏在系统关键驱动中发生
* 内存非常有限,比如在嵌入式系统或便携设备中
* 当运行于一个终止时内存并不自动释放的操作系统(比如AmigaOS)之上,而且一旦丢失只能通过重启来恢复。
[解决办法]
[解决办法]
现在内存都不归码农们管理了
[解决办法]
Java的内存回收很让人无语,无论你是否gc,系统都不会马上帮你清理内存,如果存在公用区,内存几乎永远别指望被释放,如果存在Dll、COM通讯,内存崩溃就比较常见,而且往往还不容易发现在什么地方,用C或C++处理同样的问题,调用同样的接口,内存问题却少很多。实在不知道Java在干什么。
[解决办法]
c语言要求new/delete一一对应,这没有任何解决办法。
c++支持RAII基本上不需要用户写delete这个关键字
平时多用用智能指针: std::unique_ptr, std::shared_ptr, std::weak_ptr, boost::intrusive_ptr
生活更美好,想泄露都没机会,完全遵循RAII有异常也不怕。
原则就是能确定所有权/生命周期的,用unique_ptr
不能决定所有权/生命周期的,用shared_ptr。
碰到所有权可能出现环形结构的,用weak_ptr
碰到要从raw_pointer获得shared_ptr的,用enable_shared_from_this
碰到自带引用计数(比如COM)的,用intrusive_ptr
[解决办法]
指针泄露问题并不都是因为new、delete,相反,很多问题都是来自于很简单的操作。
指针最容易出现问题的地方来自于指针的再赋值,当一个指针向另一个指针进行赋值时,就有可能引发指针超界行为,这对于一些链表类指针几乎实在难得,由于不恰当的赋值有可能导致连标断链或指向不确定区域,最终出现泄漏或是异常不确定操作,系统的风险极大。只能指针并不能完全解决这种类似逻辑的问题,就像你对一个浮点数进行精确比较一样,从语言成面没有任何错误,但是在实际操作上,判断两数相等的语句几乎永远不会被执行,即便这个数载上一刻刚刚被同一个数赋值,但当+1-1以后,这个数就再也不能保证还和原来那数一样了。指针的行为有时就跟着比较一样,你必须自己学会计算指针的值变化,不然,当经过一系列的转化后,不能保证你得到的指针就是你设计所需要的。而且这中间的一系列操作都有可能引发指针的泄漏。
对于指针,有一个忠告,就是不要轻易的重载=操作,也不要随便定义类的引用、复制构造类,除非你打算将项目中所有的相关类的相关操作都做重载,否则你的这个小冲动将是引发灾难的开始。
[解决办法]
(1)首先你说得没错,只要做到new了就delete,malloc了就free,就不会出现内存泄漏。
(2) 实际的开发将是一个很大的项目,涉及的代码行可能几十万或者更多,代码的控制本身就变得很难
(3) 一个对象的生命周期,通常不是由创建对象的那个人来控制,何时来回收该对象的内存,需要根据实际场景来决定。
(4)异常的引入和各种分支的处理也会加大了内存管理的复杂程度
(5)不过内存溢出,也不是绝对没有办法,通常有静态检查和动态检查
(6)静态检查,可以通过同事间相互交叉阅读代码,或者通过工具来帮忙检查(cppcheck)
(7) 动态检查,使用purify和valgrind等工具进行检查
不过,编程的基本功才是最关键的,才是防止内存泄漏的真谛。苦练多思考,扎实语言的基础