iOS:内存泄漏代码
Posted
技术标签:
【中文标题】iOS:内存泄漏代码【英文标题】:iOS: Memory leak codes 【发布时间】:2014-02-21 02:41:00 【问题描述】:谁能告诉我为什么下面的代码在 ARC 下会泄漏内存?我用 Instruments 对它们进行了测试,结果显示它们会导致内存泄漏,但我不知道如何修复它们?
static inline NSString* cachePathForKey(NSString* directory, NSString* key)
return [directory stringByAppendingPathComponent:key]; //leak
@property (nonatomic,strong) NSMutableData *postBody;
if (![self postBody])
[self setPostBody:[NSMutableData data]]; //leak
另一个问题:仪器向我显示“所有堆分配”和“所有匿名 VM”Live Bytes。例如,如果一个应用程序占用超过 80M(例如),它将崩溃。那么 80M 意味着 All Heap Allocations 还是 Both ?
更新:
正如下面我的一个 cmets 所述,我现在正在努力将非 ARC ASIHttpRequest 更改为 ARC 模式。泄漏来了。以 ASIInputStream 为例:
+ (id)inputStreamWithData:(NSData *)data request:(ASIHTTPRequest *)theRequest
ASIInputStream *theStream = [[self alloc] init]; //leak 42%
[theStream setRequest:theRequest];
NSInputStream *is = [NSInputStream inputStreamWithData:data]; //leak 58%
[theStream setStream:is];
return theStream;
【问题讨论】:
在我看来,我不像是泄密者! 如何告诉你它们导致了内存泄漏? 这是在后台线程中调用的吗? @ClayBridges 工具显示红色泄漏标志,然后我打开调用树,然后找到上面的代码。 @ClayBridges 第一个显示百分比 45.8% 【参考方案1】:这是在黑暗中拍摄的,但在 C 函数上,你可以试试这个
__attribute__((ns_returns_autoreleased))
static inline NSString* cachePathForKey(NSString* directory, NSString* key)
return [directory stringByAppendingPathComponent:key]; //leak
参照。 Clang docs 了解更多信息。您也可以尝试摆脱static inline
,看看是否有帮助。
【讨论】:
不,都不起作用。我现在真的很困惑泄漏的来源:(我现在正在努力将非 ARC ASIHttpRequest 更改为 ARC 模式。并且泄漏来了。以 ASIInputStream 为例:` + (id)inputStreamWithData:(NSData *)data 请求: (ASIHTTPRequest *)theRequest ASIInputStream *theStream = [[self alloc] init]; //leak 42% [theStream setRequest:theRequest]; NSInputStream *is = [NSInputStream inputStreamWithData:data]; //leak 58% [theStream setStream: is]; return theStream; ` @ZhaoRocky 我冒昧地将这些信息更新到您上面的问题中。【参考方案2】:如果您正在混合使用 ARC 和非 ARC 代码,那么很难在没有看到全局的情况下向您提供建议。我不知道你的技能水平如何,但我会引导新手不要尝试这种混合。
我通过将您的一段代码放入一个新的 Empty ios 应用程序中测试了它;看起来像这样:
这是我完整的 AppDelegate 实现,它除了不断运行您的 cachePathForKey
函数之外什么都不做。
#import "AppDelegate.h"
@implementation AppDelegate
static inline NSString* cachePathForKey(NSString* directory, NSString* key)
return [directory stringByAppendingPathComponent:key]; //leak
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
while (YES)
@autoreleasepool
NSString *s = cachePathForKey(@"/my/fake/dir", @"key");
return YES;
@end
我运行它 Xcode,Product > Profile,当 Instruments 启动时,我选择 Memory > Leaks。它没有发现任何问题。您可以尝试像这样从头开始构建,看看是否可以通过这种方式找到问题。
另一种技术是复制您的项目(或分支;我强烈推荐版本控制,尤其是git
)。然后开始剥离代码,直到你得到非常少的仍然泄漏的代码。然后您可以将该代码发布到某处; github 很常见,可以作为一个小块——gist——或者作为一个完整的 Xcode 项目。
无论是自上而下还是自下而上,这都是令人沮丧和费力的,就像一个困难的科学发现或一个难以捉摸的警察调查一样。但是,以顽强的决心解决这些问题是成为软件开发人员的重要组成部分。这里有一个非常有帮助的社区。祝你好运。
【讨论】:
以上是关于iOS:内存泄漏代码的主要内容,如果未能解决你的问题,请参考以下文章