【问题标题】:How to find the leaky faucet that loads into Malloc 32kb如何找到加载到 Malloc 32kb 中的漏水龙头
【发布时间】:2011-02-07 17:41:15
【问题描述】:

我一直在搞乱泄漏,试图找出哪个函数没有被释放(我还是新手),真的可以利用一些经验丰富的洞察力。

我有这段代码似乎是罪魁祸首。每次我按下调用此代码的按钮时,都会额外分配 32kb 的内存给内存,当释放按钮时,内存不会被释放。

我发现每次调用AVAudioPlayer来播放m4a文件时,解析m4a文件的最终函数是MP4BoxParser::Initialize(),这反过来又通过Cached_DataSource::ReadBytes分配了32kb的内存

我的问题是,我如何在完成后解除分配,以便每次按下按钮时都不会继续分配 32kb?

非常感谢您提供的任何帮助!

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

//stop playing
theAudio.stop;


// cancel any pending handleSingleTap messages 
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleSingleTap) object:nil];

UITouch* touch = [[event allTouches] anyObject]; 


NSString* filename = [g_AppsList objectAtIndex: [touch view].tag];

NSString *path = [[NSBundle mainBundle] pathForResource: filename ofType:@"m4a"];  
theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];  
theAudio.delegate = self; 
[theAudio prepareToPlay];
[theAudio setNumberOfLoops:-1];
[theAudio setVolume: g_Volume];
[theAudio play];
}

【问题讨论】:

    标签: iphone objective-c memory-leaks avaudioplayer


    【解决方案1】:

    Cocoa 中内存管理的诀窍是平衡对allocretaincopy 的任何调用与对release 的后续调用。

    在这种情况下,您发送alloc 来初始化您的theAudio 变量,但您永远不会发送release

    假设您一次只能播放一种声音,最好的方法是使用控制器上的属性(具有此-touchesBegan 方法的控制器)。属性声明如下所示:

    @property (nonatomic, retain) AVAudioPlayer * theAudio;
    

    然后,您需要在您的 init 方法中将 theAudio 设置为 nil

    theAudio = nil; // note: simple assignment is preferable in init
    

    并确保在您的 dealloc 方法中释放变量:

    [theAudio release];
    

    现在,您的 touchesBegan 可能如下所示:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    
        //stop playing
        theAudio.stop;
        ...
        AVAudioPlayer * newAudio = [[AVAudioPlayer alloc] initWithContentsOfUrl:...];
        self.theAudio = newAudio; // it is automatically retained here...
    
        theAudio.delegate = self; 
        [theAudio prepareToPlay];
        [theAudio setNumberOfLoops:-1];
        [theAudio setVolume: g_Volume];
        [theAudio play];
    
        [newAudio release];       // ...so you can safely release it here
    }
    

    【讨论】:

    • 您能解释一下您指的是哪个init 方法吗? (再次,对不起,我对此很陌生)
    • 而且,只是为了验证我是否理解这一点:你的意思是我需要将音频加载到一个额外的分配变量中,这样我就不会试图释放当前的 m4a 文件(或最终调用一块已释放的内存)我想我的问题是,theAudio 是否仍会每次都分配额外的内存,因为在调用 dealloc() 之前它不会被释放?
    • 通常来说,每个控制器都有-initdealloc 方法。我可以假设这是UIViewController吗?如果是这样,覆盖的正确方法是 -initWithNibName:bundle:另一种选择是在 viewDidLoad 方法中将您的 ivar 设置为 nil。
    • 回答你的第二个问题:self.theAudio = newAudio 这一行在幕后处理了很多“魔法”。它实际上在分配(和保留)新对象之前在旧对象上调用dealloc。这可确保释放为旧实例分配的所有内存。
    • 在您的 dealloc 方法中对 release 的最终调用只是在释放控制器本身时释放存储在 ivar 中的最后一个对象。
    【解决方案2】:

    这条线在我看来是罪魁祸首:

    theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];  
    

    这个资源什么时候释放?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-20
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多