内存泄露问题改进(转自vczh)
参考:http://www.cppblog.com/vczh/archive/2010/06/22/118493.html
参考:https://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html
C++实谓各种语言中的软肋,功能强大,陷阱更强大。当然我认为一门语言用得不好完全是程序员的责任,不过因为C++涉及到的概念实在是太多,想用好实在也不是一件容易的事情。C++开发的时候总是会遇到各种各样的问题,其中最严重的无非是内存相关的。C语言由于结构简单,内存处理起来虽然不得力,但总的来说惯用法已经深入人心,因此也不会造成什么很难发现的错误。C++就不一样了。有了虚函数、构造函数、析构函数、复制构造函数和operator=重载之后,还是有很多人喜欢把一个类直接写进文件流,或者拿来memset,代码一团乱麻,不知悔改也。但是不能因此因噎废食,就像某人因为C++带来的心智问题太多,自己搞不定,自己团队也搞不定,就说C++不好一样。
因此第一篇文章主要针对内存来讲。我们处理内存,第一件事就是不要有内存泄露。内存泄露不能等到测试的时候,通过长时间运行程序并观察任务管理器的方法来做,这显然已经晚了。幸好Visual C++给了我们一个十分好用的工具:_CrtDumpMemoryLeaks函数。这个函数会在Debug模式下往Visual Studio的output窗口打印出那个时候你new(malloc)了但是还没delete(free)的所有内存块的地址、长度、前N个字节的内容和其他信息。怎么做呢?其实很简单:
#include <stdlib.h>
#include <crtdbg.h>
#include <windows.h>
int wmain(vint argc , wchar_t* args[])
{
// 这里运行程序,并在下面的函数调用之前delete掉所有new的东西
_CrtDumpMemoryLeaks();
return 0;
}
我们只需要在注释的地方完成我们程序的功能,然后确信自己已经delete掉所有应该delete的东西,最后_CrtDumpMemoryLeaks()函数调用的时候就可以打印出没被delete的东西了。这个方法十分神奇,因为你只需要在main函数所在的cpp文件这么#include一下,所有的cpp文件里面的new都会受到监视,跟平常所用的用宏把new给换掉的这种破方法截然不同。如果你使用了全局变量的话也要小心,因为全局变量的析构函数是在main函数结束之后才执行的,因此如果在全局变量的析构函数里面delete的东西仍然会被_CrtDumpMemoryLeaks函数当成泄露掉的资源对待。当然本人认为全局变量可以用,但是全局变量的赋值必须在main里面做,释放也是,除非那个全局变量的构造函数没有申请任何内存,所以这也是一个很好的检查方法。
(添加:因为这里是针对程序运行结束后进行判断是否存在内存泄露,所以可以配合自建malloc函数添加打印获取分配的内存地址,来配合判断是否存在内存泄露以及内存泄露的地址~);
不过上面也仅仅是一个告诉你有没有内存泄漏的方法罢了。那么如何避免内存泄露呢?当然在设计一些性能要求没有比操作系统更加严格的程序的时候,可以使用以下方法:
1、如果构造函数new了一个对象并使用成员指针变量保存的话,那么必须在析构函数delete它,并且不能有为了某些便利而将这个对象的所有权转让出去的事情发生。
2、在能使用shared_ptr的时候,尽量使用shared_ptr。shared_ptr只要你不发生循环引用,那么这个东西可以安全地互相传递、随便你放在什么容器里面添加删除、你想放哪里就放在哪里,再也不用考虑这个对象的生命周期问题了。
3、不要在有构造函数和析构函数的对象上使用memset(或者memcpy)。如果一个对象需要memset,那么在该对象的构造函数里面memset自己。如果你需要memset一个对象数组,那也在该对象的构造函数里面memset自己。如果你需要memset一个没有构造函数的复杂对象,那么请为他添加一个构造函数,除非那是别人的API提供的东西。
4、如果一个对象是继承了其他东西,或者某些成员被标记了virtual的话,绝对不要memset。对象是独立的,也就是说父类内部结构的演变不需要对子类负责。哪天父类里面加了一个string成员,被子类一memset,就欲哭无泪了。
5、如果需要为一个对象定义构造函数,那么连复制构造函数、operator=重载和析构函数都全部写全。如果不想写复制构造函数和operator=的话,那么用一个空的实现写在private里面,确保任何试图调用这些函数的代码都出现编译错误。
6、如果你实在很喜欢C语言的话,那麻烦换一个只支持C不支持C++的编译器,全面杜绝因为误用了C++而导致你的C坏掉的情况出现。
什么是循环引用呢?如果两个对象互相使用一个shared_ptr成员变量直接或者间接指向对方的话,就是循环引用了。在这种情况下引用计数会失效,因为就算外边的shared_ptr全释放光了,引用计数也不会是0的。
内存泄露问题改进(转自vczh)的更多相关文章
- java: web应用中不经意的内存泄露
前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...
- 基于HTML5的WebGL应用内存泄露分析
上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...
- Android学习系列(36)--App调试内存泄露之Context篇(上)
Context作为最基本的上下文,承载着Activity,Service等最基本组件.当有对象引用到Activity,并不能被回收释放,必将造成大范围的对象无法被回收释放,进而造成内存泄漏. 下面针对 ...
- .Net内存泄露原因及解决办法
.Net内存泄露原因及解决办法 1. 什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈.非托管堆和托管堆.这里我们需 ...
- [Android Memory] App调试内存泄露之Context篇(上)
转载自:http://www.cnblogs.com/qianxudetianxia/p/3645106.html Context作为最基本的上下文,承载着Activity,Service等最基本组件 ...
- JavaScript 中 4 种常见的内存泄露陷阱
了解 JavaScript 的内存泄露和解决方式! 在这篇文章中我们将要探索客户端 JavaScript 代码中常见的一些内存泄漏的情况,并且学习如何使用 Chrome 的开发工具来发现他们.读一读吧 ...
- 深入ThreadLocal之三(ThreadLocal可能引起的内存泄露)
threadlocal里面使用了一个存在弱引用的map,当释放掉threadlocal的强引用以后,map里面的value却没有被回收.而这块value永远不会被访问到了. 所以存在着内存泄露. 最好 ...
- 找出并解决 JavaScript 和 Dojo 引起的浏览器内存泄露问题
简介: 如果大量使用 JavaScript 和 Ajax 技术开发 Web 2.0 应用程序,您很有可能会遇到浏览器的内存泄漏问题.如果您有一个单页应用程序或者一个页面要处理很多 UI 操作,问题可能 ...
- vld(Visual Leak Detector) 内存泄露检测工具
初识Visual Leak Detector 灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题.当程序越来越复 杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题.内存 ...
随机推荐
- spring中的增强类型
在spring中有两种增强方式:XML配置文件和注解配置.下面一次为大家讲解. 使用的是Aspectj第三方框架 纯POJO (在XML中配置节点) 使用@AspectJ,首先要保证所用的JDK 是5 ...
- Unity Ray 射线
射线:射线是3D世界一个向一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射. 用途:射线范围比较广,多用于碰撞检测(如:子弹飞行是否击中目标).角色移动等. Ray是一个结 ...
- Django-DRF组件学习-预备知识
1.web开发应用模式 在开发Web应用中,有两种应用模式: 1.1 前后端不分离 所谓的前后端不分离,就是前后端数据都在同一个服务器中,前端的样式以及页面渲染都由后端一次性渲染出来在前端浏览器中展示 ...
- 操作系统安全 - 提权 - Windows提权 - 汇总
CVE_2019-1388 Date: -- 影响范围: SERVER ====== Windows 2008r2 ** link OPENED AS SYSTEM ** Windows 2012r2 ...
- 删除MicrosoftOffice2016的扫尾工作
因为用到一些画流程图之类的工具,想到以前用的Visio挺好用的,就找来安装一下,结果因为装了Microsoft Office2016在安装时报错不断,先说下网上的帖子:用OfficeDeploymen ...
- 005 gcc 的简单使用
0. 前言 本文主要讲关于 gcc 的几种编译方式 不妨设文件名为 test.c 1. 方法一 $ gcc test.c (Windows OS)编译成功的话,没有回馈,在 test.c 所在的文件夹 ...
- [转帖]CGI与ISAPI的区别(转)
CGI与ISAPI的区别(转) 不知道原始网站是哪个 博客园里面也是转帖的 https://www.cnblogs.com/eret9616/p/8515095.html 不过我还是不了解CGI和IS ...
- JAVA获取当前系统时间System.currentTimeMillis()以及获取运行时间
System.currentTimeMillis()产生一个当前的毫秒,这个毫秒其实就是自1970年1月1日0时起的毫秒数,Date()其实就是相当于Date(System.currentTimeMi ...
- JAVA poi设置单元格背景颜色
import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.ss.usermodel.Ce ...
- A+B and A*B problem 大数相加 相乘 模拟
A+B and A*B problem 大数相加 相乘 模拟 题意 给你两个数a和b,这两个数很大,然后输出这两个数相加的和,相乘的积. 解题思路 模拟,但是还是搜了搜代码实现,发现这个大佬写的是真的 ...