iOS: CGImageCreateWith [PNG ou JPEG] O DataProvider causa falha de segmentação
Estou enfrentando um problema estranho. Estou desenvolvendo um utilitário de scanner de código de barras da linha de comando do iOS usando libzbar (sim, isso é para dispositivos desbloqueados). Tudo vai bem, exceto quando estou tentando usar oCGImageCreateWithPNGDataProvider()
ouCGImageCreateWithJPEGDataProvider()
métodos para obter umCGImageRef
de um arquivo - porque essas duas funções lançam um segfault no meu iPad 5.1.1. O problema não está na minha classe personalizada,ZBarScanner
, porque se eu usar um UIImage para obter os dados da imagem, usando algo como
UIImage *uiImage = [UIImage imageWithContentsOfFile:fname];
CGImageRef image = uiImage.CGImage;
então funciona bem e imprime os dados armazenados no código de barras. Além disso, as imagens PNG e JPEG são bem formatadas - posso visualizá-las usando um navegador de arquivos no próprio dispositivo e também tentei várias outras imagens. Eu até tentei omitir todo oCFRelease()
chamadas de função erelease
mensagens, a fim de evitar ter ponteiros pendentes. Aqui está meu código:
#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;
}
Se eu executar no depurador (GDB e desordem NSLog removido para maior clareza):
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)
Então, mesmo o backtrace não mostra nada obviamente errado / útil ... Parece quealguma coisa é nuloalgum lugar. Eu até suspeitei que, devido a minha toolchain ser uma compilação não oficial baseada em 4.0, essas funções podem não estar disponíveis no iOS 5.1.1, então a compilação é bem-sucedidaCGImageCreateWith[...]DataProvider
símbolos estão dentro dodesenvolvimento sysroot mas não entre iOS 'real bibliotecas dinâmicas, mas se este fosse o caso, o ponteiro de função I NSLogged seriaNULL
, certo? No entanto, nenhum dos objetos NS e CG nem as funções parecem ser NULL - o único NULL que eu passo para os construtores CGImage é umdecodeArray
parâmetro, mas é explicitamente mencionado na documentação da Apple que pode ser NULL ... (Atualizar: Eu tentei passar uma matriz não-NULL válida para descobrir se a documentação está errada, mas ainda tenho o mesmo erro).
Você poderia me dar algumas dicas (trocadilho intencional) sobre esse acidente? O que estou perdendo aqui? Todos os tutoriais e referências que encontrei até agora sugerem o uso de CGDataProvider e CGImage como este.