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
    

另一个问题:仪器向我显示“所有堆分配”和“所有匿名 VMLive 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:内存泄漏代码的主要内容,如果未能解决你的问题,请参考以下文章

关于IOS内存泄漏

如何修复 _NSCFNumber 的 iOS 内存泄漏?

内存泄漏,在do-catch块中。 iOS,Swift

根据仪器的iOS内存泄漏

iOS PDFKit 内存泄漏

MKMapView 在 iOS10 中检测内存泄漏