Java와 동등한 C ++이 있습니까?
try {
...
}
catch (Throwable t) {
...
}
기본 Windows 기능을 호출하는 Java / jni 코드를 디버깅하려고하는데 가상 시스템이 계속 충돌합니다. 네이티브 코드는 단위 테스트에서 잘 보이고 jni를 통해 호출 할 때만 충돌하는 것 같습니다. 일반적인 예외 포착 메커니즘은 매우 유용합니다.
Java와 동등한 C ++이 있습니까?
try {
...
}
catch (Throwable t) {
...
}
기본 Windows 기능을 호출하는 Java / jni 코드를 디버깅하려고하는데 가상 시스템이 계속 충돌합니다. 네이티브 코드는 단위 테스트에서 잘 보이고 jni를 통해 호출 할 때만 충돌하는 것 같습니다. 일반적인 예외 포착 메커니즘은 매우 유용합니다.
답변:
try{
// ...
} catch (...) {
// ...
}
모든 C ++ 예외를 포착하지만 나쁜 디자인으로 간주해야합니다. c ++ 11의 새로운 current_exception 메커니즘을 사용할 수 있지만 c ++ 11 (재 작성이 필요한 레거시 코드 시스템)을 사용할 수 없으면 메시지 나 이름을 얻는 데 사용할 명명 된 예외 포인터가 없습니다. . 포착 할 수있는 다양한 예외에 대해 별도의 catch 절을 추가하고 맨 아래에있는 모든 항목 만 포착하여 예기치 않은 예외를 기록 할 수 있습니다. 예 :
try{
// ...
} catch (const std::exception& ex) {
// ...
} catch (const std::string& ex) {
// ...
} catch (...) {
// ...
}
누군가는 C ++ 코드에서 "크래쉬"를 잡을 수 없다고 덧붙여 야한다. 그들은 예외를 던지지 않지만 좋아하는 것을합니다. 널 포인터 역 참조로 인해 프로그램이 중단되면 정의되지 않은 동작을 수행하는 것입니다. 없습니다std::null_pointer_exception
. 예외를 잡으려고해도 도움이되지 않습니다.
누군가 가이 스레드를 읽고 프로그램 충돌의 원인을 얻을 수 있다고 생각하는 경우를 대비하여. 대신 gdb와 같은 디버거를 사용해야합니다.
try { .. } catch(...) { ... }
신호 / 서명을 사용하여 잡기 위해 구현할 때까지 "캐치"라고 부르지 않을 것입니다. : 신호 처리기에서 프로그래머가 코드에서 충돌이 발생한 위치를 알기가 비교적 어렵습니다. try / catch와 비교하여 프로그래밍 방식으로 감지하는 방법).
catch(...)
GCC를 사용하여 필요한 경우 예외 유형을 내부에서 리버스 엔지니어링 할 수있는 방법입니다 (타사 라이브러리에서 알 수없는 경우 유용 할 수 있음).
#include <iostream>
#include <exception>
#include <typeinfo>
#include <stdexcept>
int main()
{
try {
throw ...; // throw something
}
catch(...)
{
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
}
return 1;
}
부스트 를 사용할 여유가 있다면 캐치 섹션을 더 간단하게 (외부에서) 크로스 플랫폼으로 만들 수 있습니다
catch (...)
{
std::clog << boost::current_exception_diagnostic_information() << std::endl;
}
try {
// ...
} catch (...) {
// ...
}
참고 그 ...
안에catch
즉, 실제 줄임표이다. 세 개의 점.
그러나 C ++ 예외는 반드시 기본 Exception
클래스의 서브 클래스 일 필요 는 없으므로이 구문을 사용할 때 발생하는 예외 변수를 실제로 볼 수있는 방법은 없습니다.
catch
주석 ( // ...
) 에서 기존 코드 자리 표시 자와 지정자 를 구별한다고 말했습니다 .
모든 예외를 이식 가능한 방식으로 잡을 수는 없습니다 (C ++에서). 일부 예외는 C ++ 컨텍스트에서 예외가 아니기 때문입니다. 여기에는 0으로 나누기 오류 및 기타 항목이 포함됩니다. 이러한 오류가 발생할 때 해킹하여 예외를 던질 수는 있지만, 쉽게 수행 할 수없고 이식 가능한 방식으로 올바르게 얻는 것은 쉽지 않습니다.
모든 STL 예외를 잡으려면 할 수 있습니다
try { ... } catch( const std::exception &e) { ... }
을 사용하면 e.what()
을 반환 const char*
하여 예외 자체에 대해 더 많이 알 수 있습니다. 이것은 당신이 가장 많이 요구 한 Java 구조와 유사한 구조입니다.
누군가가 상속받지 않은 예외를 던질만큼 바보 인 경우에는 도움이되지 않습니다 std::exception
.
요컨대을 사용하십시오 catch(...)
. 그러나 기본적으로 다음 catch(...)
과 함께 사용됩니다 throw;
.
try{
foo = new Foo;
bar = new Bar;
}
catch(...) // will catch all possible errors thrown.
{
delete foo;
delete bar;
throw; // throw the same error again to be handled somewhere else
}
이것이 올바른 사용 방법 catch(...)
입니다.
Foo
않습니까? 소멸자 가 실행 됩니까? 나는 그것이 RAII의 요점이라고 생각했다. 그러나 스택에 스택을 Foo
생성 하는 대신 포인터가 필요한 경우 Foo
스택에 선언 된 다른 포인터로 래핑해야합니다.
다음과 같이 작성하면됩니다 :
try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}
그러나 여기에는 눈에 띄지 않는 위험이 있습니다. try
블록 에 발생한 정확한 유형의 오류를 찾을 수 없으므로 catch
예외 유형에 관계없이 프로그램이 지속되어야한다는 것을 확신 할 때이 유형을 사용 하십시오 catch
블록에 정의 된 방식으로 .
당신이 사용할 수있는
catch(...)
그러나 그것은 매우 위험합니다. John Robbins는 자신의 저서 인 Debugging Windows 에서 catch (...) 명령에 의해 가려진 정말 불쾌한 버그에 대한 전쟁 이야기를 들려줍니다. 특정 예외를 잡는 것이 훨씬 낫습니다. try 블록이 합리적으로 발생할 수 있다고 생각하는 것을 잡으십시오.하지만 실제로 예기치 않은 일이 발생하면 코드에서 예외를 더 높게 발생시킵니다.
여기에 이것을 언급하겠습니다 : Java
try
{
...
}
catch (Exception e)
{
...
}
모든 예외를 잡을 수는 없습니다! 나는 실제로 이런 종류의 일이 전에 일어 났으며, 그것은 도발적인 일입니다. 예외는 Throwable에서 파생됩니다. 문자 그대로 모든 것을 잡기 위해 예외를 잡기를 원하지 않습니다. Throwable을 잡고 싶습니다.
나는 그것이 nitpicky처럼 들리지만, 당신이 try ... catch (Exception e) "블록으로 둘러싸인 코드에서"언제나 예외 "가 어디서 왔는지 알아 내려고 며칠을 보냈을 때 당신.
catch(Exception)
Java에서 모든 예외를 잡을 수는 없습니다. C # ... Java = catch(Thowable)
, C # = 과 섞여 catch(Exception)
있습니다. 혼동하지 마십시오.
CoderMalfunctionError
은 (실제로 자바 Error
서브 클래스입니다 ... 소리가 나지 않는 것은 아닙니다.)
예를 들어 미니 덤프를 만들기 위해 모든 예외를 잡으려면 ...
누군가가 Windows에서 작업을 수행했습니다.
http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus를 참조 하십시오 .이 기사에서는 모든 종류의 예외를 포착하는 방법을 발견하고 작동하는 코드를 제공합니다.
잡을 수있는 목록은 다음과 같습니다.
SEH exception
terminate
unexpected
pure virtual method call
invalid parameter
new operator fault
SIGABR
SIGFPE
SIGILL
SIGINT
SIGSEGV
SIGTERM
Raised exception
C++ typed exception
그리고 사용법 : CCrashHandler ch; ch.SetProcessExceptionHandlers (); // 하나의 스레드에 대해이 작업을 수행합니다. ch.SetThreadExceptionHandlers (); // 각 쓰레드마다
기본적으로 현재 디렉토리 (crashdump.dmp)에 미니 덤프가 생성됩니다.
일반적인 예외 포착 메커니즘은 매우 유용합니다.
못 미더운. 코드가 충돌했기 때문에 이미 코드가 손상되었음을 알고 있습니다. 예외를 먹는 것은 이것을 숨길 수도 있지만 아마도 더 나쁘고 더 미묘한 버그가 발생할 수도 있습니다.
당신이 정말로 원하는 것은 디버거입니다 ...
콘솔 창에서 JNI를 사용하는 Java 애플리케이션을 실행하여 (Java 명령 행에서 실행) JVM이 충돌하기 전에 발견 된 내용에 대한 보고서가 있는지 확인할 수 있습니다. Java 창 응용 프로그램으로 직접 실행하는 경우 대신 콘솔 창에서 실행하면 표시되는 메시지가 누락 될 수 있습니다.
둘째, JNI DLL 구현을 스텁하여 DLL의 메소드가 JNI에서 입력되고 올바르게 리턴되는지 등을 보여줄 수 있습니까?
C ++ 코드에서 JNI- 인터페이스 메소드 중 하나를 잘못 사용하여 문제점이 발생하는 경우 간단한 JNI 예제가 컴파일되어 설정과 작동하는지 확인 했습니까? 특히 매개 변수를 네이티브 C ++ 형식으로 변환하고 함수 결과를 Java 유형으로 변환하기 위해 JNI 인터페이스 메소드를 사용하려고 생각합니다. 데이터 변환이 작동하고 COM과 유사한 호출에서 JNI 인터페이스로 이동하지 않도록하기 위해 이들을 스텁하는 것이 유용합니다.
확인해야 할 다른 것들이 있지만, 네이티브 Java 메소드가 무엇인지, 그리고 JNI 구현이 무엇을 시도하는지에 대해 더 알지 못하면 제안하기가 어렵습니다. C ++ 코드 수준에서 예외를 잡는 것이 문제와 관련이 있는지 확실하지 않습니다. (JNI 인터페이스를 사용하여 예외를 Java로 다시 던질 수는 있지만, 이것이 제공하는 것이 확실하지는 않습니다.)
JNI를 사용하는 프로그램을 제대로 디버깅 할 수 없다는 실제 문제 (또는 디버거에서 실행할 때 버그가 나타나지 않음) :
이 경우 JNI 호출 주위에 Java 래퍼를 추가하는 것이 도움이됩니다 (즉, 모든 기본 메소드는 개인용이며 클래스의 공용 메소드는이를 호출하여). 해제 후) 또는 동기화 (하나의 DLL에서 단일 객체 인스턴스로 모든 메소드를 동기화) 후에는 사용되지 않습니다. 자바 래퍼 메소드가 실수를 기록하고 예외를 던지도록하십시오.
이것은 종종 대규모 병렬 Java 프로그램을 디버그하려고 시도하는 것보다 실제 오류 (놀랍게도 대부분 불쾌한 더블 프리 또는 이와 유사한 원인이되는 호출 된 함수의 의미를 따르지 않는 Java 코드에 있음)를 찾는 데 도움이됩니다. 네이티브 디버거 ...
원인을 알고 있으면 코드를 피하는 래퍼 메소드에 코드를 보관하십시오. JNI 코드가 VM을 충돌시키는 것보다 래퍼 메소드가 예외를 발생시키는 것이 좋습니다 ...
알고
try{
// ...
} catch (...) {
// ...
}
캐치 유일한 언어 수준의 예외 같은 다른 낮은 수준의 예외 / 오류 Access Violation
및이 Segmentation Fault
잡힐 실 거예요.