iOS:CGImageCreateWith DataProvider导致分段错误

我正面临一个奇怪的问题。 我正在开发一个使用libzbar的iOS命令行条形码扫描器工具(是的,这是为越狱设备)。 除了当我试图使用CGImageCreateWithPNGDataProvider()CGImageCreateWithJPEGDataProvider()方法从文件中获取CGImageRefCGImageRef我的5.1.1 iPad上这两个函数抛出了段CGImageRef ,否则CGImageCreateWithJPEGDataProvider()正常。 这个问题不在我的自定义类ZBarScanner ,因为如果我使用UIImage来获取图像数据,

 UIImage *uiImage = [UIImage imageWithContentsOfFile:fname]; CGImageRef image = uiImage.CGImage; 

那么它工作正常,打印存储在条码中的数据。 此外,PNG和JPEG图像格式良好 – 我可以使用设备上的文件浏览器查看它们,并尝试了其他几种图像。 我甚至试图省略所有的CFRelease()函数调用并release消息,以避免悬挂指针。 这是我的代码:

 #define LOG() NSLog(@"Reached line %d", __LINE__) int main(int argc, char **argv) { if (argc != 2) return 1; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; LOG(); // line 21 NSString *fname = [[NSString stringWithUTF8String:argv[1]] retain]; // added an extra retain just in case LOG(); // line 25 CFDataRef data = (CFDataRef)[NSData dataWithContentsOfFile:fname]; CGDataProviderRef dProv = CGDataProviderCreateWithCFData(data); // I also tried using // dProv = CGDataProviderCreateWithFilename(argv[1]); // that made no difference either. The data and data provider are // valid, but the CGImage constructors always segfault. if (dProv == NULL) { fprintf(stderr, "Invalid CGDataProvider\n"); abort(); } LOG(); // line 34 CGImageRef image = NULL; if ([[fname pathExtension] isEqualToString:@"png"]) { LOG(); // line 39 NSLog(@"Function pointer: %p", CGImageCreateWithPNGDataProvider); image = CGImageCreateWithPNGDataProvider(dProv, NULL, false, kCGRenderingIntentDefault); // This function segfaults, or... LOG(); } else if ([[fname pathExtension] isEqualToString:@"jpg"] || [[fname pathExtension] isEqualToString:@"jpeg"]) { LOG(); image = CGImageCreateWithJPEGDataProvider(dProv, NULL, true, kCGRenderingIntentDefault); // ... or this one. LOG(); } else { fprintf(stderr, "File '%s' is neither a PNG nor a JPEG file!\n", argv[1]); LOG(); abort(); } LOG(); // CFRelease(dProv); LOG(); ZBarScanner *scanner = [ZBarScanner zbarScannerWithCGImage:image]; // CFRelease(image); LOG(); NSArray *arr = [scanner scan]; NSLog(@"The result of the scanning is:\n%@", arr); LOG(); [pool drain]; return 0; } 

如果我在debugging器中运行它(清除GDB和NSLog杂波):

 gdb ./scanner (gdb) run ./barcode1.png Reached line 21 Reached line 25 Reached line 34 Reached line 39 Function pointer: 0x37c5b535 Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x00000000 0x00000000 in ?? () (gdb) backtrace #0 0x00000000 in ?? () (gdb) 

所以即使回溯也没有显示任何明显的错误/有帮助…似乎某些东西是NULL的地方 。 我甚至怀疑由于我的工具链是一个非官方的基于4.0的版本,这些函数可能在iOS 5.1.1中不可用,所以CGImageCreateWith[...]DataProvider成功,因为CGImageCreateWith[...]DataProvider符号位于开发系统根iOS的实际dynamic库,但如果是这样的话,函数指针我NSLogged了将NULL ,对吧? 然而,NS和CG对象和函数似乎都不是NULL – 我传递给CGImage构造函数的唯一NULL是decodeArray参数,但是在Apple的文档中明确提到它可以是NULL …( 更新 :I尝试传递一个有效的非NULL数组,以查明文档是否是错误的,但我仍然有相同的错误)。

请给我任何关于这次事故的指示(双关语)? 我在这里错过了什么? 到目前为止我发现的所有教程和参考文献都提示使用CGDataProvider和CGImage就像这样。

当使用文件名时,苹果文档中的示例代码使用您在评论中提到的尝试的组合,加上值kCGRenderingIntentPerceptual而不是缺省值:

  CGDataProviderRef pngDP = CGDataProviderCreateWithFilename([filePath fileSystemRepresentation]); if (pngDP) { CGImageRef img = CGImageCreateWithPNGDataProvider(pngDP, NULL, true, kCGRenderingIntentPerceptual); // true for interpolate, false for not-interpolate 

这样做会使你不必将数据保存在你的程序中,并且可以防止你看到的段错误。

(至less,也许可以得到并尝试在iOS官方文档中find的CoreTextPageViewer示例代码,构build该项目,并试图弄清楚你在做什么是不同的。)