2010-11-23 4 views
0

Obj-C MyStreamHandler.mm 클래스 파일에 libxml 오류 처리기를 생성하여 할당했습니다. 스트림 파서는 xmlTextReaderSetErrorHandler를 사용한다. 오류 처리기에서 나는 [NSException raise:format:]을 사용하여 Obj-C 예외를 발생시킵니다. 그러나 그것의 내에서 Obj-C 클래스 내에서 예외가 catch되지 않습니다. @try/@catch 블록입니다.Obj-C에서 libxml 오류 처리기 콜백 함수 (Obj-C++)에서 Obj-C 예외가 발생했습니다. Obj-C에서 catch되지 않았습니다.

libxml에서 잘못된 xml이 발견되면 (예 : </foo </bar>) 콜백이 발생합니다. 오류 처리기가 많이 호출되고 있으며 NSException도 발생하는 것으로 알려져 있습니다. 그러나 예외는 libxml의 클라이언트 인 Obj-C 클래스에서 잡히지 않습니다.

다음
 
<foo><bar</foo>

아래 캐치되지 않는 예외에 의한 관련된 호출 스택의 다음은 MyStreamHandler.mm

#import <libxml/xmlreader.h> 

#import "MyStreamHandler.h" 

void MyErrorCallback(void *arg, const char *msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator); 

@implementation MyStreamHandler 

-(void)readStream:(xmlTextReaderPtr)streamAPI 
{ 
    xmlTextReaderSetErrorHandler(streamAPI, (xmlTextReaderErrorFunc)MyErrorCallback, NULL); 

    @try 
    { 
     while (xmlTextReaderRead(streamAPI) == 1) 
     { 
      // Loop through the XML until the malformed XML is hit. 
     } 
    } 
    @catch (id e) 
    { 
     NSLog(e); 
    } 
} 

@end 

void MyErrorCallback(void *arg, const char *msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator) 
{ 
    [NSException raise:@"MyException" format:@"Something bad happened: %s",msg]; 
}

이 콜백과 예외를 발생하게하는 샘플 XML 파일입니다 :

*** Terminating app due to uncaught exception 'MyException', reason: 'Something bad happened: Opening and ending tag mismatch: content line 0 and container 
' 

*** Call stack at first throw: 
(_NSCallStackArray*)0x10301a40; count=33 { 
0 CoreFoundation      0x04324be9 __exceptionPreprocess + 185 
1 libobjc.A.dylib      0x044795c2 objc_exception_throw + 47 
2 CoreFoundation      0x042dd628 +[NSException raise:format:arguments:] + 136 
3 CoreFoundation      0x042dd59a +[NSException raise:format:] + 58 
4 MyApp        0x00ee1b85 _Z25MyErrorCallbackPvPKc19xmlParserSeveritiesS_ + 319 
5 libxml2.2.dylib      0x0401766c xmlTextReaderStandalone + 105 
6 libxml2.2.dylib      0x04018793 xmlTextReaderSetErrorHandler + 838 
7 libxml2.2.dylib      0x03f69c78 __xmlRaiseError + 1222 
8 libxml2.2.dylib      0x03f6d564 namePush + 1283 
9 libxml2.2.dylib      0x03f75e2c xmlParseXMLDecl + 1291 
10 libxml2.2.dylib      0x03f80b6d xmlParseChunk + 3984 
11 libxml2.2.dylib      0x0401a255 xmlTextReaderGetAttribute + 816 
12 libxml2.2.dylib      0x0401bb34 xmlTextReaderRead + 441 
13 MyApp        0x00ec2919 +[MyStreamHandler readStream:] 
... 
Application call stack 
... 
24 CoreFoundation      0x0429567d __invoking___ + 29 
25 CoreFoundation      0x04295551 -[NSInvocation invoke] + 145 
26 Foundation       0x027bd555 -[NSInvocationOperation main] + 51 
27 Foundation       0x0272bbd2 -[__NSOperationInternal start] + 747 
28 Foundation       0x0272b826 ____startOperations_block_invoke_2 + 106 
29 libSystem.B.dylib     0x925a0024 _dispatch_call_block_and_release + 16 
30 libSystem.B.dylib     0x925922f2 _dispatch_worker_thread2 + 228 
31 libSystem.B.dylib     0x92591d81 _pthread_wqthread + 390 
32 libSystem.B.dylib     0x92591bc6 start_wqthread + 30 
} 
terminate called after throwing an instance of 'NSException' 

완전히 가짜입니까? Obj-C++ 함수 내에서 Obj-C 예외를 던져서 Obj-C 코드의 정상적인 @ try/@ catch 블록을 통해 처리 할 수 ​​있습니까? 또는 Obj-C++ try/catch 블록을 사용하여 실제 Obj-C++ 예외를 발생시켜야합니까?

도움을 주시면 감사하겠습니다.

답변

1

코코아 및 코코아 터치의 예외는 프로그래머 오류 전용입니다. 최종 사용자에게 제공되는 프로덕션 코드에서이 코드를 사용하지 않아야합니다.

중간 스택 프레임을 모두 제어하는 ​​경우에만 일반적으로 API 경계를 통해 발생하는 예외를 catch 할 수는 없습니다. 따라서 예제에서 보았 듯이 Objective-C 예외에 대한 지식이없는 코드에서 예외가 발생하므로 유효한 상태로 남지 않을 수 있습니다.

오류 처리기에서 다른 방식으로 오류 정보를 상위 수준 코드로 전달해야합니다. 일반적으로 콜백 및 콜백 등록 API가 의 최종 인수와 같이 void * 인수를 갖는 이유는 무엇입니까? 이는 콜백과 일부 컨텍스트를 연결하여 결정을 내릴 수 있도록합니다. 여러 개의 가능한 문서 중 어떤 것이 읽었을지라도 오류가 발생했습니다.

+0

우리의 패턴은 파일 판독기에서 예외를 사용하여 응용 프로그램에 제어권을 넘겨주기 전에 패턴을 잡는 것입니다. 그런 다음 NSError **로 변환 한 다음 그 때부터 사용합니다. 크리스에게 감사드립니다. – xmlhack

+0

Java 또는 .NET 플랫폼에서 익숙하지 않은 패턴을 사용하면 안됩니다. 임의의 C 코드에서 예외를 던져 Objective-C 또는 C++에서 catch 할 수는 없습니다. C 코드에서 사용되는 상태가 일관성을 잃어 충돌, 정지, 보안 악용 등이 발생할 수 있습니다. –

+0

임의의 C 코드가 아니며 상태가 일관성이 없습니다. 이것은 Java 또는 .NET 플랫폼에서 사용되지도 않습니다. 이것은 거의 10 년 동안 선적 된 Objective-C 및 Obj-C++ 코드입니다. 우리는 이미 필요한 퍼지 테스트를 수행했습니다. – xmlhack

0

예외 패러다임은 여분의 코드를 사용하지 않아도되므로 일반적으로 예외 패러다임이 더 깨끗한 코드로 이어지기 때문에 예외에 대한 Apple의 조언을 잘 아는 사람은 아닙니다. 특수 문자는 별도로 설정할 필요가 없습니다. 오류를 나타내는 값을 리턴합니다.

Objective-C 예외가 예상치 못한 코드에서 전파되는 것을 절대적으로 허용 할 수 없습니다. 이는 Objective-C 예외를 처리하기 위해 많은 코드가 작성되지 않았기 때문입니다. 예를 들어 libxml2은 누출 및 기타 불쾌감을 유발하여 스택을 풀지 않을 것입니다.

예외가 처리기에 의해 캐치되지 않는 이유는 모르겠지만 (어쩌면 @throw해야 함) 그와 관련이 없습니다. 이 상황에서는 사용할 수 없습니다.

콜백에서 수행해야 할 작업은 오류가 있었음을 기록하는 것일뿐입니다. 기록하거나 기록한 다음 정상적으로 돌아 오는 것입니다. 오류가 치명적일 경우 libxml2는 사용자가 도움을받지 않고 종료하는 방법을 알게됩니다.

+0

해결책은 스트림 작업에서 libxml2의 -1 응답 값을 포착하고 오류를 처리하는 동안 속도가 느리고 제어 된 스택을 사용하는 것입니다. 이것은 명백하게 작동하지 않는 예외를 던지기위한 훨씬 간단한 방법 대신에 그렇게하는 것이 아니라면 그렇게하는 것이 좋습니다. – xmlhack

관련 문제