内存泄漏问题的解决
内存泄漏(Memory Leaks)是当一个对象或变量在使用完成后没有释放掉,这个对象一直占有着这块内存,直到应用停止。如果这种对象过多内存就会耗尽,其它的应用就无法运行。这个问题在C++、C和Objective-C的MRR中是比较普遍的问题。
在Objective-C中释放对象的内存是发送release和autorelease消息,它们都是可以将引用计数减1,当为引用计数为0时候,release消息会使对象立刻释放,autorelease消息会使对象放入内存释放池中延迟释放。
上代码:
- (void)viewDidLoad { [super viewDidLoad]; NSBundle *bundle = [NSBundle mainBundle]; NSString *plistPath = [bundle pathForResource:@"team" ofType:@"plist"]; //获取属性列表文件中的全部数据 self.listTeams = [[NSArray alloc] initWithContentsOfFile:plistPath]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listTeams objectAtIndex:row]; cell.textLabel.text = [rowDict objectForKey:@"name"]; NSString *imagePath = [rowDict objectForKey:@"image"]; imagePath = [imagePath stringByAppendingString:@".png"]; cell.imageView.image = [UIImage imageNamed:imagePath]; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listTeams objectAtIndex:row]; NSString *rowValue = [rowDict objectForKey:@"name"]; NSString *message = [[NSString alloc] initWithFormat:@”您选择了%@队。”, rowValue]; UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@”请选择球队” message:message delegate:self cancelButtonTitle:@”Ok” otherButtonTitles:nil]; [alert show]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; }
大 家看看上面的3个方法会有什么问题呢?如果代码是基于ARC的是没有问题的,遗憾的是基于MRR,上面的代码都存在内存泄漏的可能性。理论上讲内 存泄漏是对象或变量没有释放引起的,但实践证明并非所有的未释放对象或变量都会导致内存泄漏,这与硬件环境和操作系统环境有关,因此我们需要检测工具帮助 我们找到这些“泄漏点”。
在Xcode中提供了两种工具帮助查找泄漏点:Analyze和Profile,Analyze是静态分析工具 可以通过菜单 Product→Analyze启动,为静态分析之后的代码画面;Profile是动态分析工具,这个工具叫“Instruments”,它是Xcode 集成在一起,可以在Xcode中通过菜单Product→Profile启动,Instruments有很多Trace Template(跟踪模板)可以动态分析和跟踪内存、CPU和文件系统。
我们可以两个工具结合使用查找泄漏点,先使用Analyze静态分析查找可疑泄漏点,再用Profile动态分析中的Leaks和Allocations跟踪模板进行动态跟踪分析,确认这些点是否泄漏,或者是否有新的泄漏出现等。
其 中的线段表明了程序执行的路径,在这个路径中,1:说明在25行Objective-C对象引用计数是1,说明在这里创建了一个 Objective-C对象;2:说明在27行引用计数为1这个,该对象没有释放,怀疑有泄漏。这样的说明已经很明显的告诉我们问题所在了, [[NSArray alloc] initWithContentsOfFile:plistPath]创建了一个对象,并赋值给 listTeams属性所代表的成员变量,然而完成了赋值工作之后,创建的对象并没有显示地发送release和autorelease消息。代码修改
NSArray *array = [[NSArray alloc] initWithContentsOfFile:plistPath];
self.listTeams = array;
[array release];
我们看一下tableView:cellForRowAtIndexPath:方法中的疑似泄漏点行末尾的蓝色图标展开分析结果
其 中主要是说明UITableViewCell*类型的cell对象在64行有可能存在泄漏。在表视图中 tableView:cellForRowAtIndexPath:方法是为表视图单元格实例化并设置数据的,因此cell对象实例化后不能马上 release,应该使用autorelease延迟释放。可以在创建cell对象的时候发送autorelease消息,代码修改如下:
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
我们看一下tableView:didSelectRowAtIndexPath:方法中的疑似泄漏点有两个,行末尾的图标展开分析结果。
message对象创建之后没有释放,我们只需要在[alert show]之后添加[message release]语句代码就可以了。在Objective-C中实例化对象有两种方式:
NSString *message = [[NSString alloc] initWithFormat:@”您选择了%@队。”, rowValue]; ①
NSString *message = [NSString stringWithFormat:@"您选择了%@队。", rowValue]; ②
① 行所示以init-开头构造方法,它的是在alloc之后调用该方法我们称为“实例构造方法”,该方法创建对象所有权是调用者,调用者需要对它的 生命周期负责,具体说负责创建和释放。而另一种是②行所示string-(去掉NS后类名)开头方法,它是通过类直接调用我们称为“类级构造方法”,该方 法是创建的对象所有权非调用者所有,调用者不无权释放它,否则就会因过渡释放而“僵尸化”,这个问题我们会在下一节介绍。
UIAlertView*类型alert对象创建之后没有释放,我们只需要在[alert show]之后添加[alert release]语句代码就可以了,修改之后的代码
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listTeams objectAtIndex:row]; NSString *rowValue = [rowDict objectForKey:@"name"]; NSString *message = [[NSString alloc] initWithFormat:@”您选择了%@队。”, rowValue]; UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@”请选择球队” message:message delegate:self cancelButtonTitle:@”Ok” otherButtonTitles:nil]; [alert show]; [alert release]; [message release]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; }
上 面介绍的使用Analyze静态分析查找可疑泄漏点,之所以称为“可疑泄漏点”,但是这些点未必一定泄漏,确认这些点是否泄漏还要通过 Profile动态分析工具Instruments中的Leaks和Allocations跟踪模板,Analyze静态分析只是一个理论上的预测过程。 通过菜单Product→Profile启动, Profile动态分析工具中选择Leaks模板
Instruments 中虽然是选择了Leaks模板,但默认情况也会添加Allocations模板,基本上凡是分析内存都会使用 Allocations模板,它可以监控内存分布情况,选中Allocations模板(图中①区域),右边③区域会显示随着时间的变化内存使用折线图 表,同时在④区域会显示内存使用的详细信息,其中刚刚对象分配情况。点击Leaks模板(图中②区域),可以查看内存泄漏情况,如果在③区域有红线出现, 则有内存泄漏,④区域会显示泄漏的对象。
出 现的泄漏是在点击表视图中单元格测试tableView:didSelectRowAtIndexPath:方法方法时候发生的,其中 NSCFString类型的对象发生了泄漏,NSCFString类型在NSFoundation中是NSString*类型。点击泄漏对象前面的三角形 展开对象,可以看到它们的内存地址、占用字节、所属框架和响应方法信息。
打开扩展详细视图,可以看到右边的跟踪堆栈信息,其中我们自己应用代码,可以点击进入我们程序代码,会打开对应代码。
代码77并不是泄漏点,而是其中的NSString*类型对象在之后发生了泄漏,因此可以断定是message对象之后没有释放导致泄漏。我们修改代码如下:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listTeams objectAtIndex:row]; NSString *rowValue = [rowDict objectForKey:@"name"]; NSString *message = [[NSString alloc] initWithFormat:@”您选择了%@队。”, rowValue]; UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@”请选择球队” message:message delegate:self cancelButtonTitle:@”Ok” otherButtonTitles:nil]; [alert show]; [message release]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; }
添 加[message release]语句。很多人还会猜测alert对象(UIAlertView*)会有泄漏,因此重新运行Instruments工具,反复点击单元格测 试,并未发现表示内存泄漏的红线! Instruments工具认为alert对象不释放不会引起内存泄漏,如果我们想进一步评估它对于内存的应用,这个时候我们可以看看 Allocations模板的折线图表,每次点击总占用内存数都有所增加,这说明alert对象没有释放虽然不是很严重,但是也会增加占用内存,因此 alert对象释放也是必须的。
这就是我们介绍的内存泄漏问题解决方法,事实上内存泄漏是极其复杂问题,工具使用是一方面,经验是另一方面。提高经验,然后借助于工具才是解决内存泄漏的根本。
相关推荐
- **性能优化**:了解UICollectionView的性能优化策略,提高应用程序的流畅度。 ##### 2.4 Classbook项目 - **项目背景**:介绍Classbook项目的背景和目标,理解其应用场景。 - **功能实现**:通过实践,学习如何...
- **问题解决**:在开发过程中可能会遇到的各种问题及其解决方案,如内存泄漏、性能瓶颈等。 #### 七、进阶话题 - **多线程编程**:学习如何利用多线程技术提高游戏性能。 - **自定义渲染器**:深入了解OpenGL ES...
【基于zepto的移动端轻量级日期插件–date_picker】是专为移动Web开发设计的日期选择解决方案,旨在解决现有插件过于依赖大型库、功能复杂度高、不适合移动端性能优化的问题。这款插件的核心目标是保持轻量化、低...
内容概要:本文介绍了如何利用CST软件进行三维超材料的能带计算。首先概述了三维超材料的独特性质及其广泛应用前景,接着简要介绍了CST软件的功能特点。随后详细阐述了能带计算的具体步骤,包括模型建立、材料参数设置、网格划分与求解设置以及最终的计算与结果分析。最后给出了一段Python代码示例,展示了如何处理CST输出的数据并绘制能带图。文章强调了计算机模拟技术对于深入了解超材料电子结构和物理性质的重要性。 适合人群:从事材料科学研究的专业人士,尤其是对三维超材料和电磁场模拟感兴趣的科研工作者和技术人员。 使用场景及目标:适用于希望借助CST软件开展三维超材料能带计算的研究项目,旨在提高对超材料的理解,推动相关领域的技术创新和发展。 其他说明:文中提供的Python代码仅为示例,在实际操作时可根据具体情况进行调整优化。同时,掌握CST软件的基本操作和电磁理论基础知识有助于更好地理解和应用本文内容。
内容概要:本文详细介绍了基于FPGA的永磁同步伺服系统的矢量控制设计,涵盖了从电流环到速度环的关键模块实现。具体包括Clarke和Park变换、PI调节器、AD7606采样、正交编码器反馈以及SVPWM生成等部分。文中提供了详细的Verilog代码片段,展示了各个模块的具体实现方法和技术细节。特别强调了定点数处理、时序设计和跨时钟域处理等方面的技术挑战及其解决方案。 适合人群:具备一定FPGA开发经验和电机控制基础知识的研发人员。 使用场景及目标:适用于希望深入了解FPGA在电机控制应用中的具体实现方式,特别是矢量控制和电流环设计的专业人士。目标是掌握FPGA平台下高效、低延迟的电机控制系统设计方法。 阅读建议:由于涉及大量具体的Verilog代码和硬件设计细节,建议读者在阅读过程中结合实际项目进行实验和调试,以便更好地理解和掌握相关技术。
经典飞机大战游戏是理解实时交互系统设计的绝佳载体。本文将深入剖析现代空战游戏的核心模块,涵盖刚体运动学、弹道轨迹优化、碰撞检测算法等关键技术,揭示二维游戏背后复杂的三维数学建模过程。
scratch少儿编程逻辑思维游戏源码-冰塔.zip
scratch少儿编程逻辑思维游戏源码-弹跳(4).zip
内容概要:本文详细介绍了COMSOL软件中三种常见的焊接热源模型——双椭球热源、高斯旋转体热源和柱状体热源。双椭球热源适用于模拟移动热源(如激光焊、电弧焊),通过调整轴向系数a1和a2来控制热流分布;高斯旋转体热源适合小范围焊接,采用三维高斯函数描述热流密度;柱状体热源则用于深熔焊场景,特点是计算速度快。文中还提供了每种模型的具体代码实现,并强调了调试时需要注意的关键点,如时间步长、网格加密等。此外,作者分享了一些实用技巧,如将热源参数设置为全局变量并利用参数扫描功能提高调试效率。 适合人群:从事焊接工艺仿真、材料加工领域的研究人员和技术人员,以及对COMSOL建模感兴趣的工程技术人员。 使用场景及目标:帮助用户选择合适的热源模型进行焊接模拟,确保模拟结果的准确性;提供具体的代码实现和调试方法,使用户能够快速掌握并应用于实际项目中。 其他说明:文中提到的热源模型不仅限于理论介绍,还包括实际操作中的注意事项和优化建议,有助于提升模拟效果和工作效率。
内容概要:本文介绍了将基于RBF神经网络的PID控制器应用于永磁同步电机(PMSM)转速环控制的方法及其性能优势。传统的PID控制器在面对非线性和时变系统时存在参数整定困难的问题,而引入RBF神经网络可以实现实时在线调参,提高系统的灵活性和鲁棒性。文中详细描述了Simulink模型的设计,特别是Matlab s-function模块中RBF神经网络的具体实现,包括高斯函数激活和带惯性的权值更新机制。实验结果显示,在转速突变情况下,改进后的控制器能够迅速稳定系统,超调量控制在2%以内,调节时间较传统方法缩短约40%,并且在负载变化时表现出色,无需重新整定参数。 适合人群:从事电机控制系统研究和开发的技术人员,尤其是对PID控制器优化感兴趣的工程师。 使用场景及目标:适用于需要提升PMSM转速环控制精度和响应速度的应用场合,如工业自动化设备、机器人等领域。目标是通过引入智能算法解决传统PID控制器参数整定难题,提高系统性能。 阅读建议:关注RBF神经网络与PID控制器结合的具体实现细节,特别是在Matlab s-function模块中的编码技巧以及参数调整策略。同时,注意学习率的选择和动量项的作用,这对于实际应用至关重要。
scratch少儿编程逻辑思维游戏源码-GTA 6.zip
scratch少儿编程逻辑思维游戏源码-仓鼠跑酷.zip
scratch少儿编程逻辑思维游戏源码-超级麦克世界.zip
scratch少儿编程逻辑思维游戏源码-400年.zip
少儿编程scratch项目源代码文件案例素材-气球足球.zip
少儿编程scratch项目源代码文件案例素材-沙漠迷城.zip
scratch少儿编程逻辑思维游戏源码-比谁高.zip
少儿编程scratch项目源代码文件案例素材-乾坤大挪移.zip
scratch少儿编程逻辑思维游戏源码-菜鸟跳跃.zip