UIImagePNGRepresentation中出现png_error,仅限于iOS 5.1+。

10

我们遇到了一个奇怪的崩溃,其中UIImagePNGRepresentation()有时会导致png_error调用。在我们内部的任何设备上都无法重现此错误。

以下是我们HockeyApp崩溃日志中的堆栈跟踪示例:

Thread 0 Crashed:
0   libsystem_kernel.dylib         0x3167132c __pthread_kill + 8
1   libsystem_c.dylib              0x33d6729f abort + 94
2   ImageIO                        0x346c38bf png_error + 114
3   ImageIO                        0x346c2fe3 png_write_end + 46
4   ImageIO                        0x346bf069 writeOnePng + 2260
5   ImageIO                        0x346be78b _CGImagePluginWritePNG + 82
6   ImageIO                        0x346be6fd CGImageDestinationFinalize + 132
7   UIKit                          0x31346e23 UIImagePNGRepresentation + 274
我们只在运行 iOS 5.1 及以上版本的设备上看到这些崩溃日志。我们也因为 iOS 6 而遭遇了一些崩溃,因此这个 bug 还没有被修复。
我编写了一个测试应用程序,下载了我们的应用程序可能显示的超过16,000张图片,所有图片都能够顺利地下载并保存到磁盘中,没有问题。一些对这个gist的回应暗示着这个问题可能是由于损坏的图像引起的,但是考虑到我已经下载了超过16,000张图片,并且从来没有出现过问题,我觉得这不可能是原因。
我目前正在研究的最新假设是,下载的数据某种方式受到损坏,因此会创建一个损坏的 UIImage。然而,所有尝试创建损坏的 UIImage 的尝试都失败了。苹果似乎已经为 UIImage 创建了一个健壮的构造函数,因此,任何我传递的无效参数都会返回构造函数的 nil。
有其他人从 UIImagePNGRepresentation 中经历过类似的情况吗?

1
你知道这个崩溃发生在哪个设备上吗?它只是iPhone、iPod touch或iPad吗? - runmad
我们在所有设备上都看到了这个问题,但主要是iPhone4,1、iPhone3,1和iPhone2,1...但我认为这只是因为我们的用户群。我还没有按注册设备进行归一化处理。 - Senior
也许是低内存错误?如果你将所有的PNG文件读入内存,malloc()最终会返回0... - user529758
好主意 - 我刚刚创建了一个泄漏的应用来测试这个,但它只是通过kill -9命令杀死了该应用。 - Senior
你解决了这个问题吗?我遇到了一个类似的错误,但是稍微有些不同:3 ImageIO 0x320857c4 _cg_png_error + 84 - leftspin
不好意思。我们最终切换到了另一个图像缓存库,这解决了问题。很可能是在不同的线程上获取PNG表示时出现了问题。 - Senior
5个回答

0

我在我的生产应用程序中遇到了一个类似的本地图像损坏问题已经几个月了(在我的情况下使用UIImageJPEGRepresentation()),而且在我的情况下,它与下载图像无关 - 而是与本地存储和渲染有关。

在我的情况下,错误的实际用户效果是图像只会部分呈现;图像的其余部分只会出现灰色和损坏。我正在使用Core Data进行磁盘存储和读取(但是Core Data令人震惊地不是我的问题)。

我的解决方法:

我以前使用这个便利方法:

UIImage *image = [UIImage imageWithContentsOfFile:imagePath];

但是在这里的一些其他相关帖子的建议下, 我改用了这种方法组合:

NSData *resultData = [NSData dataWithContentsOfFile:imagePath];
UIImage *image = [UIImage imageWithData:resultData];

...看起来它似乎解决了我的问题!

我的理论

我猜测imageWithContentsOfFile:在处理一些非原子边缘情况时,比纯粹的基础NSData调用更差,并且由于某种原因允许'读'在上一个'写'完成之前开始。

希望这可以帮到你!祝好运。


我认为这可能是一个不同的问题,与我们在这里遇到的问题不同。问题不在于将NSData序列化为UIImage,而是当UIImage被序列化为NSData时,执行此操作的线程会收到终止信号,并且由于这是在UI线程上发生的(本身就是一个问题),因此应用程序会崩溃。 - Reid Main

0
如果调用 UIImagePNGRepresentation 的代码在一个循环内,我在另一个 SO thread 上看到了一个解决方法,建议在保存后添加 sleep(1.0);

不幸的是,这是在Web图像缓存上,可能会被调用数百次每秒。 - Senior

0

我们在一个大规模运行的应用程序中遇到了这个问题。它每天发生超过1000次。使用Crashlytics的日志记录功能,我们能够确定导致崩溃的确切图像。

大约有25张图片触发了崩溃。我们意识到,这些图片中的每一张都是从Photoshop导出的,而我们大多数的图片都是从Illustrator导出的。这些图片在我们尝试的其他所有程序中都可以正常渲染,我们从未能确定它们有什么“问题”。但是我们重新从Illustrator导出了这些图片,我们的崩溃率降至零。

我知道这并没有提供根本原因,但我认为对于其他遇到此问题的人可能会有所帮助。


0

你试过用不同的网络条件进行测试吗?尝试使用3G或EDGE而不仅仅是WiFi。尝试使用网络链接变速器模拟慢速和丢包网络的条件。


我不明白创建PNG文件与网络条件有什么关系...UIImagePNGRepresentation只有在图像下载完成后才会被调用。 - Senior
是的,但您可能会得到一个已损坏或部分下载的图像。 - brynbodayle
在我的原始帖子中,我提到我们创建了损坏的图像并对其进行了测试,但没有成功。不过还是感谢您的建议。 - Senior

0

你是否从第二线程中进行任何UIKit调用?我曾经看到过一些在第二线程上运行的UIKit图形调用工作,但主线程在稍后某个时刻会崩溃。有一些UIKit方法可以在第二线程上使用,但并不多。


不幸的是,pkill 在线程0上。我们正在主线程上执行UIImagePNGRepresentation调用,这很有趣,因为我正要将其移出以避免阻塞,但我想这可能会使情况变得更糟? - Senior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接