2014-02-21 206 views
1

有人能告诉我为什么下面的代码在ARC下泄漏内存?我用Instruments测试了它们,它显示它们会导致内存泄漏,但我不知道如何修复它们?iOS:内存泄漏代码

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直播字节。例如,如果一个应用程序占用超过80M(例如),它会崩溃。那么80M意味着全部堆分配两者都

UPDATE:

正如下面我评论人提到,我现在工作的变化非ARC ASIHttpRequest电弧模式。泄漏来了。就拿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; 
} 
+0

我似乎不是泄漏给我! – Merlevede

+0

它是如何告诉你它们会导致内存泄漏? –

+1

这是否在后台线程中调用? – Pang

回答

0

这是一个在黑暗中拍摄,但在C函数,你可以试试这个

__attribute__((ns_returns_autoreleased)) 
static inline NSString* cachePathForKey(NSString* directory, NSString* key) { 
    return [directory stringByAppendingPathComponent:key]; //leak 
} 

参看Clang docs欲了解更多信息。你也可以尝试摆脱static inline,看看是否有帮助。

+0

不,一切都不起作用。我现在对于泄漏来自哪里感到非常困惑:( 我现在正在处理将非ARC ASIHttpRequest更改为ARC模式,并且泄漏出现。以ASIInputStream为例:' +(id)inputStreamWithData:(NSData *)data请求:(ASIHTTPRequest *)theRequest { \t ASIInputStream * theStream = [[自的alloc] INIT]; //泄漏42% \t [theStream了setRequest:theRequest]; NSInputStream *是= [NSInputStream inputStreamWithData:数据];//泄漏58% \t [theStream setStream:是]; \t回theStream; } ' –

+0

@ZhaoRocky我冒昧地把这些信息在更新到您上面的问题。 –

0

如果您将ARC和非ARC代码混合在一起,那么很难在没有看到大图的情况下给出建议。我不知道你的技能水平是什么,但我会让新手远离尝试这种混合。

我测试了一段代码,将它放在一个新的空的 iOS应用程序中;看起来是这样的:

enter image description here

这里是我的完整的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,产品>档案,当仪器启动后,我选择内存>泄漏。它没有发现问题。你可以尝试从头开始建立起来,看看你是否可以通过这种方式找到问题。

另一种技术是复制你的项目(或分支;我强烈建议版本控制,特别是git)。然后开始剥离代码,直到找到仍然泄漏的最小代码。然后,您可以在某处发布该代码; github很常见,或者作为一个小块 - 一个gist - 或作为一个完整的Xcode项目。无论哪种方式,自上而下或自下而上,这是令人沮丧和费力的,就像一个困难的科学发现,或一个难以捉摸的警方调查。但是,通过顽强的决心解决这些问题是成为软件开发人员的重要组成部分。这里有一个非常有帮助的社区。祝你好运。