[英]“Received memory warning” while running app on device
I'm working on an iPhone Video decoder application. 我正在开发iPhone视频解码器应用程序。 I need to convert raw pixel data for each frame and render it on the screen continuously (Hence forming a video). 我需要为每个帧转换原始像素数据,并在屏幕上连续渲染(因此形成视频)。 The function below is the one that renders each frame on the screen. 下面的功能是一种在屏幕上渲染每一帧的功能。
- (void)drawBufferWidth:(int)width height:(int)height pixels:(unsigned char*)pixels
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef gtx = CGBitmapContextCreate(pixels, width, height, BitsPerComponent, BytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
myimage = CGBitmapContextCreateImage(gtx); //myimage is of type CGImageRef
CGContextRelease(gtx);
img.image = [UIImage imageWithCGImage:myimage]; //img is of type UIImageView
[CATransaction flush];
CGImageRelease(myimage);
myimage = Nil;
}
The code is working absolutely fine on the simulator. 该代码在模拟器上可以正常工作。 When I run it on the device, it displays few frames, gives "Received memory warning" and crashes. 当我在设备上运行它时,它显示几帧,并显示“接收到内存警告”并崩溃。
I'm not able to figure out where the problem is. 我无法弄清楚问题出在哪里。 Am I not deallocating properly or even though I'm releasing the image, it is still existing in the memory, thus eating up the memory? 我是否没有正确分配内存,或者即使我释放映像,映像仍存在于内存中,从而耗尽了内存?
Kindly help! 请帮助!
Thanks in advance. 提前致谢。
EDIT: 编辑:
The Xcode organizer says the following: Xcode组织者说:
hevcd[665] has active assertions beyond permitted time:
{(
<SBProcessAssertion: 0x11aacf70> identifier: Suspending process: hevcd[665] permittedBackgroundDuration: 10.000000 reason: suspend owner pid:565 preventSuspend preventThrottleDownCPU preventThrottleDownUI
)}
A couple of observations: 一些观察:
Let's imagine that you have a for
loop: 假设您有一个for
循环:
for (i = start; i < end; i++) { // doing lots of memory intensive stuff }
You must recognize that any memory that is auto released during this loop will not actually be yielded back to the operating system until that loop completes and the auto release pool is flushed. 您必须认识到,在该循环过程中自动释放的任何内存实际上都不会退还给操作系统,直到该循环完成并且刷新自动释放池为止。 When doing memory intensive operations, you could theoretically do: 理论上,当执行内存密集型操作时,您可以执行以下操作:
for (i = start; i < end; i++) { @autorelease { // doing lots of memory intensive stuff } }
That way, you're manually creating a new autorelease pool that will be flushed with greater frequency. 这样,您可以手动创建一个新的自动释放池,该池将以更高的频率刷新。
Having said that, you really should not be doing prolonged tasks that do not yield back to the operation system (at least on the main thread, and because you're doing UI stuff, you have to do that on the main thread). 话虽如此,您实际上不应该执行长时间的任务,这些任务不会退回到操作系统上(至少在主线程上,并且因为您正在执行UI事务,所以必须在主线程上执行此操作)。 A better model than performing some prolonged for
loop would be let the operating system call your code at some regular interval. 与执行延长for
循环相比,更好的模型是让操作系统每隔一定的时间间隔调用代码。 Then the standard autorelease pool will do it's job and you should be fine. 然后,标准的自动释放池就可以完成工作,您应该会很好。 You create a timer like so: 您可以这样创建一个计时器:
- (void)startTimer { self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES]; }
You then have a routine to handle the timer: 然后,您有一个例程来处理计时器:
- (void)handleTimer:(NSTimer *)timer { // do what you need here }
Make sure that you turn off your timer (eg when the view disappears), or else when this view controller is dismissed, it won't be released because the timer will maintain its strong reference to it and you'll have a retain cycle (or strong reference cycle) and you'll leak memory. 确保关闭计时器(例如,当视图消失时),否则关闭该视图控制器时,将不会释放它,因为计时器将保持对它的强烈引用,并且您将拥有一个保留周期(或强大的参考周期),您将泄漏内存。
- (void)viewWillDisappear:(BOOL)animated { [self.timer invalidate]; }
You can achieve similar functionality using CADisplayLink
, too. 您也可以使用CADisplayLink
实现类似的功能。 You can create the display link: 您可以创建显示链接:
- (void)startDisplayLink { self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)]; [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } - (void)handleDisplayLink:(CADisplayLink *)displayLink { // do what you need here }
and again, you'd want to make sure you stop it when you're done: 再次,您需要确保在完成后将其停止:
- (void)viewWillDisappear:(BOOL)animated { [self.displayLink invalidate]; }
All three of those scenarios could probably remedy your memory situation (unless you have some undetected retain cycle or leak). 所有这三种情况都可能会纠正您的内存状况(除非您有一些未检测到的保留周期或泄漏)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.