您的位置:首页 > 其它

检测iphone内存泄漏-内存泄漏工具教程(译)

2012-02-29 19:24 363 查看
在国外的网站上看到了一个关于内存泄漏的文章,觉得不错就翻译了一下!

(译:随着我的游戏开发周期接近尾声我使用Instruments的次数也越来越多,”Instruments:Xcode自带的一组工具,所以结尾加了个S”因为我发现在这个工具用来在检测我的游戏内存泄漏超好用,于我就想写一篇关于如何用这个工具来检测内存泄漏的快速入门教程!PS:分享精神值得表扬!好同学啊!)

(内存泄漏?为什么要关注它?)

(内存泄漏是程序对已经分配的内存失去控制/跟踪,结果就会导致这个分配的内存永远无法被程序释放.会产生这些内存占用的情况一般是使用了:”new”,”malloc”,”alloc”而没有相对应的使用:”delete”,”free”,”release”,PS:还有”autorelease”)

(当你使用”new”,”malloc”,”alloc”的时候,操作系统就会从内存中划一块相应的内存出来供你使用,系统对你说:”给你,这是给你使用的那块内存的地址”.系统希望你保护好这个地址(引用址址,或者指针)并且相信你会在不用这个内存时告诉他.(用”delete”,”free”,”release”告诉系统,我不用这块内存了))

(内存泄漏发生在你把你的内存引用地址/指针给弄丢了,系统也就无法从你的一堆内存分醒中找出那里已经释放了,那些没有释放!)

(为什么要关注内存泄漏?大多数情况下当用户退出你的应用时你浪费的内存也会相应的释放,不会生产很大的影响,但是更差的就是程序运行时每帧都产生的内存泄漏,这将直接导致你的程序崩溃,特别是程序运行的时间很长的情况下!)

(想了解更多关于内存泄漏,可以直接去维基百科看下:)

http://en.wikipedia.org/wiki/Memory_leak

如何检测内存泄漏?

(有些内存泄漏可以直接看代码就能发现,但是有些就比较复杂,那么就该主角Instruments上场了,Instruments有一个”Leaks”的工具可以确切的告诉你什么地方发生了内存泄漏,你可以直接去这个地方修复!)

一个例子应用

(我准备好了有两个内存泄漏的应用,其中一处在Objective-C view controller中,还有一处在 C++ 的类中,你们可以到相应的地址下载,下面是代码片段)

InstrumentsTestViewController.mm Excerpts
// Leaky excerpts - see GitHub for complete source

- (void)viewDidLoad {
[super viewDidLoad];

LeakyClass* myLeakyInstance = new LeakyClass();
delete myLeakyInstance;

mMyLeakyString = [[NSString alloc] initWithUTF8String:"I'm a leaky string."];

[self doSomethingNow];
}

- (void) doSomethingNow
{
mMyLeakyString = [[NSString alloc] initWithUTF8String:
"Look, another alloc, but no release for first one!"];
}


LeakyClass.mm Excerpts
// Leaky excerpts - see GitHub for complete source

LeakyClass::LeakyClass()
{
mLeakedObject = new LeakedObject();
}

LeakyClass::~LeakyClass()
{
}


(接下我要我要用Instruments来调试我的应用了(这里作者用自己的硬件做测试,没有的同学可以用模拟器也行的!))

Instruments

(打开Instruments时,你可以看到这样一个界面,左边其实是有一个”ios simulator”可以选择的!(如果没有就装个Xcode4,我用的是4),然后双击选择”leaks”.)



(完成这步,你就可以看到这样一个界面了!)



(然后选择要执行检测的程序,这里可以直接浏览到你的程序,然后点击选中!)



(你准备好了吗?然后点击”Record”,这时工具会加载运行你的程序,并记录所有内存分配,每10秒针会自动检测一次内存泄漏!)



(当然你可以直接设置内存检测时间长度,或者关闭也行,当选中”自动检测内存泄漏”时,应用会卡住3-5秒,所以如果是在一边运行一边检测内存泄漏时就比较烦了!我一般的做法是手动操作,当我要检测泄漏时就点”check for leaks Now”(比如:当加载一个新的游戏模块时,退出游戏回到主菜单界面时,就点一下)点击一下”check for leaks Now”,然后点击右上角View那里的窗口模式把相关信息显示出来!在这个例子中我就就自动检测了!)



(当应用程序运行几秒后,自动检测就可以查出两处内存泄漏,很强大吧,那接下来做什么呢?)



Extended Detail View

Instruments非常的猥琐:也不明确提示用户接下来怎么做.你要留意底下的按钮条,看到把一个格子分白蓝两段的按钮了吧!你把鼠标移动去就会显示”Extended Detail View”,其实你也可以通过View->Extended Detail来查看.



(好吧,点一下他!出来了吧,右边打开了一个详情界面,

点击第一个左边内存泄漏点,右边栏会详细描述你的内存泄漏问题!问题出在[NSString initWithUTF8String],如果你往上看他的跟踪显示,就可以看到最后一次调用是[InstrumentsTestViewController viewDidLoad]里面.)



(接下来最酷的部分,双击”Extend Detail View”中最后调用的那行!Xcode打开了并且直接定位到这里”罪犯”这里!)



(这个例子中我们看到是由于NSString分配内存泄漏,如果要提高效率这种非常简单的泄漏只能看下就知道了!)

(在viewDidLoad视图加载完成后,我给字符段分配了内存,如:)
mMyLeakyString = [[NSString alloc] initWithUTF8String:"I'm a leaky string."];


(在dealloc释放方法中,我这样释放,看起来是没有什么问题的,对不对?)
[mMyLeakyString release];


(你第一反应是什么?这个很正常啊,怎么会?好吧!用下搜索找下这个变量共出现了几次!哈哈,找到了!)
mMyLeakyString = [[NSString alloc] initWithUTF8String:
"Look, another alloc, but no release for first one!"];


看到了吧,我又分配了一次内存给他,问题出在,我们加载时分配了一个内存,还没有来得及释放就重新分配一个内存,那么原来的内存就飘在空中了,现在没有任何引用指向他了,所以也不会被释放了啊!

好吧,来处理一下!在第二次用之前先释放一下!
- (void) doSomethingNow
{
[mMyLeakyString release];
mMyLeakyString = [[NSString alloc] initWithUTF8String:
"Look, another alloc, but released first one!"];
}


这样做的道理相当简单,但是这种做法并不是上上之选,不过如果你喜欢这样做也行.

我们来看看第二个,还是老样子双击左边第二行,然后看右边详情,找到最后一次引用是在什么地方:LeakyClass:LeakyClass().



双击它,直接找到它了!



这里使用了"new",这是?析构函数没有"delete"?这可不好,每个"new"一定要对应一个"delete",我们来改下析构函数!

LeakyClass::~LeakyClass()
{
if (mLeakedObject != NULL)
{
delete mLeakedObject;
mLeakedObject = NULL;
}
}


再重新运行一次你的程序检测内存泄漏,是不是没有了?好了,去检测一下你自己程序吧,记住,没有内存泄漏的程序才是好程序!

原文地址:http://www.mobileorchard.com/find-iphone-memory-leaks-a-leaks-tool-tutorial/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: