이렇게 테크니컬하게 답변해주시는 분은 첨 봅니다. 감사합니다.
64비트 운영체제에는 테이블 드라이븐 방식이라 예외처리 오버헤드가 없다고
말씀해주셨는데요. 어떤 메카니즘으로 오버헤드가 없게되는건지 잘모르겠습니다.
설명해주시면 감사하겠습니다.
지나다가 님이 쓰신 글 :
: 질문 님이 쓰신 글 :
: :
: : void __fastcall TForm1::Button1Click(TObject *Sender)
: : {
: : int k = 100;
: : int t = 0;
: : int r = 0;
: :
: : try {
: : r = k / t;
: : }
: : catch(...)
: : {
: : Caption = "divide zero...";
: : }
: : }
: :
: :
: : 32비트로 컴파일 하면 응용프로그램에서 캐치가 되고, 캡션에 출력도 잘되는데
: : 64비트로 컴파일 하면 응용 프로그램에서 예외 캐치를 못합니다.
: : 버그인가요?
: :
: :
: :
: :
:
:
: 이건 좀 기술적인 부분인데 컴파일러의 버그라기 보다는
: 본질적으로 엠바가 clang 오픈소스 컴파일러를 베끼면서 Exception 필터링 기능을 구현해 놓지 못했기 때문임.
:
: C++ 컴파일러에서 Exception을 구현하는 방식은 벤더마다 다르고,
: clang 오픈소스 컴파일러의 경우에는 Itanium ABI를 따르는 GNU 컴파일러의 short jmp/long jmp 방식이나
: dwart 형식 두가지 방식을 지원하도록 되어있는데, 이 방식의 경우 윈도우즈 64비트 OS 에서 native 로 제공하는
: Exception 처리 방식과 다르기 때문에 특히 Callback 함수에서 문제가 있게되어서
:
: 현재 GNU 컴파일러는 기존의 방식을 사용하지 않고 Windows 64bit OS가 native 하게 지원하는 64bit SEH 방식으로
: 컴파일러 툴체인이 컴파일 될수 있도록 Configuration 이 설정되어 있음.
:
: Windows 32 bit OS에서는 프레임 방식으로 Exception을 처리해서 예외가 발생하지 않더라도 스택 Unwind를 위한
: 에필로그 코드가 무조건 실행되는 오버헤드를 피할수 없었지만, Windows 64bit OS에서는 예외가 발생하지 않으면
: 전혀 그런 오버헤드 없이 프로그램이 실행될수 있도록 Exception 방식을 Table Driven 방식으로 근본적으로 바꿨음.
:
: 명시적으로 throw 에 의한 동기적인 예외가 아닌, CPU에 의해서 하드웨어적으로 캐치되는 비동기적 Exception을 처리하기 위해선
:
:
: void __fastcall TForm3::Button1Click(TObject *Sender)
: {
: int value = 100;
: int divider = 0;
: int r = 0;
:
: try{
: r = value / divider;
: }
: __except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
: EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
: {
: Caption = L"Divide zero";
: }
: }
:
:
: 위와 같은 코드패턴을 이용해야 함.
:
: 32비트 컴파일러로 컴파일해서 디버거에서 실행하지 않고 직접 실행하면, 캡션에 문자가 뜰 것임.
:
: 여기서 GetExceptionCode() 는 함수 처럼 보이지만, 실제는 함수가 아니고 컴파일러가 인식하는
: 내부 컴파일 디렉티브임.
:
: 32비트 컴파일러에서는 저런 Exception 필터링 기능을 지원하지만
:
: 엠바가 clang 오픈소스 컴파일러를 열심히 베껴서 만든 64bit 컴파일러는 Exception 필터링 기능을 아직
: 구현해 놓고 있지 못하고 있음.
:
: 그리고 또한가지 C++ 빌더의 근본적인 문제는 델파이 Exception 처리 방식을 따라야 하기 때문에
: 예외가 발생할시 로컬스코프의 객체만 자동으로 소멸시켜줄 뿐, 힙에 생성된 객체 까지 자동으로
: 소멸시켜주지 못함. 델파이로 만들어진 VCL을 뒷치닥거리 하기 위해서 이런 짓을 ㅋ
:
: 예외처리는 델파이 컴파일러 보다 오히려 FPC 컴파일러가 근본적으로 더 잘 만들어져 있음.
: RTL도 델파이는 Early 타임 Exception을 제대로 캐치하지 못하게 엉터리로 구현되어 있고.
:
: 사족으로 엠바카데로가 64 bit CRT 런타임 라이브러리에 대한 소스코드를 제공하고 있지 않은데
: 그래서 소스레벨 디버깅도 안되고.
:
: 그건 clang 에서 사용하는 로우레벨의 컴파일러 지원 코드들이 이를테면 예외처리를 위한 로우레벨 부분
: 컴파일러 지원을 위한 빌트인 함수등의 코드가 GNU 컴파일러 랭귀지 확장셋을 써서 구현되어 있고
: 엠바카데로 애들도 CRT 런타임 코드 컴파일을 위해서 GNU 컴파일러를 썼기 때문임.
:
: clang 은 디버깅 포맷으로 GNU 컴파일러 툴 체인이 사용하는 dwarf 포맷을 사용하는데,
: 엠바가 그놈에 파스칼 랭귀지를 사용하는 델파이 뒷치닥거리 하기 위해서 지들 편한대로
: 디버깅 포맷을 변형해서 사용하기 때문에 GNU 컴파일러로 컴파일한 모듈에 대한 디버깅도 안되고 ㅋ
:
: