6

我有一种方法需要逐个像素地解析一堆大的 PNG 图像(每个 PNG 是 600x600 像素)。它似乎在模拟器上工作得很好,但在设备(iPad)上,我在一些内存复制功能中得到了 EXC_BAD_ACCESS。似乎尺寸是罪魁祸首,因为如果我在较小的图像上尝试它,一切似乎都有效。这是下面方法的内存相关内容。

+ (CGRect) getAlphaBoundsForUImage: (UIImage*) image 
{    
    CGImageRef imageRef = [image CGImage];

NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

unsigned char *rawData = malloc(height * width * 4);
memset(rawData,0,height * width * 4);

NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGColorSpaceRelease(colorSpace);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

/* non-memory related stuff */

free(rawData);

当我在一堆图像上运行它时,它运行了 12 次然后就出错了,而在模拟器上它运行没有问题。你们有什么想法吗?

4

8 回答 8

3

转到产品 -> 编辑方案 -> 启用僵尸对象。在启用僵尸对象之前打勾。现在构建并运行它。它可以为您提供更好的 EXC_BAD_ACCES 错误描述。

于 2012-06-11T15:09:40.023 回答
3

运行 12 次然后崩溃听起来像是内存不足的问题。可能是 CGContext 在内部创建了一些大型的自动释放结构。由于您在循环中执行此操作,因此它们不会被释放,因此您会耗尽内存并死掉。

不过,我不确定 Core Foundation 如何处理临时对象。我不认为 CF 对象具有与 autorelease 等效的功能,而且 Core Graphics 上下文几乎可以肯定是在处理 CF 对象而不是 NSObjects。

为了减少代码中的内存流失,我建议在开始处理之前对其进行重构以创建一个屏幕外 CGContext,并重复使用它来处理每个图像。然后在完成后释放它。在任何情况下都会更快(因为您不会在每次通过循环时分配巨大的数据结构。)

我敢打赌这会消除你的崩溃问题,而且我敢打赌它也会让你的代码变得更快、更快。与其他操作相比,内存分配非常慢,并且您正在使用一些非常大的数据结构来处理 600x600 像素的 RGBA 图像。

于 2012-02-26T02:33:41.870 回答
0

Maybe replace

CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

with

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGColorSpaceRelease(colorSpace);

as the color space ref might still be needed somehow? Just a random guess... And maybe even put it behind the release of the context?

// cleanup
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
于 2012-06-11T23:46:16.323 回答
0

也许 CGImageGetBytesPerRow (两个的幂听起来过大)。

于 2010-04-14T00:08:19.097 回答
0

尝试在设备上运行应用程序时运行仪器分配,这很可能是与内存相关的问题。如果您处于循环中,请在该循环内创建一个自动释放池。

于 2012-03-19T06:18:50.143 回答
0

我在使用 CGImageCreate() 的 iPad(当然是 iPhoneOS 3.2)上遇到了类似的崩溃。看到你的困难给了我一个提示。我通过将我的 bytesPerRow 与 2 的下一个最大幂对齐来解决了这个问题。

size_t bytesPerRowPower2 = (size_t) round( pow( 2.0, trunc( log((double) bytesPerRow) / log(2.0) ) + 1.0 ) );

让我们知道提供 2 行对齐功能是否也可以解决您的问题。您需要使用调整后的大小分配 *rawData 并将 bytesPerRowPower2 传递给 CGBitmapContextCreate()... 高度似乎不需要对齐。

于 2010-04-13T07:32:27.503 回答
0

当我以编程方式创建图像时,我在直接定义行大小的应用程序中使用了两个对齐行大小的幂。但我也建议 toastie 在尝试我的建议之前尝试 CGImageGetBytesPerRow。

于 2010-04-14T07:04:32.933 回答
0

我通过制作方形上下文(宽度=高度)解决了这个问题。我有一个 512x256 的纹理,每次将数据发送到 OpenGL 时它都会崩溃。现在我分配了一个 512x512 的缓冲区,但仍然渲染 512x256。希望这可以帮助。

于 2012-12-30T21:21:04.950 回答