2010-05-23 8 views
62

나는 이것을 Google에 입력했지만 C++에서 howtos 만 찾았습니다.C에서 예외를 throw하는 방법은 무엇입니까?

C에서 어떻게해야합니까?

+6

C는 예외 처리를 지원하지 않습니다. C로 예외를 던지려면 Win32의 구조화 된 예외 처리와 같은 특정 플랫폼을 사용해야합니다. 그러나 이에 대한 도움을주기 위해 관심이있는 플랫폼을 알아야합니다. –

+14

... Win32 구조적 예외 처리를 사용하지 마십시오. –

+2

setjmp()와 longjmp()를 사용하면 이론적으로 작동해야하지만, 문제가 될만한 가치는 없다고 생각합니다. –

답변

44

C에서는 예외가 없습니다. C에서 오류는 함수의 반환 값, 프로세스의 종료 값, 프로세스에 대한 신호 (Program Error Signals (GNU libc)) 또는 CPU 하드웨어 인터럽트 (또는 CPU가있는 경우) (How processor handles case of division by zero).

예외는 C++ 및 다른 언어로 정의됩니다. C++의 예외 처리는 C++ 표준 "S.15 Exception handling"에 지정되어 있으며 C 표준에는 해당 섹션이 없습니다.

+2

그래서 C에서는 예외가 없다는 것을 보장합니다, 어떻게? – httpinterpret

+0

@httpinterpret : C 코드가 있다면 생각하고있는 것처럼 예외를 던질 방법이 없습니다. 반환 코드를 얻거나 정의되지 않은 동작이있는 코드에 빠질 가능성이 큽니다. –

+39

@httpinterpret : C에서 그것은 템플릿이 없거나 반사가 없거나 유니콘이 없다는 것을 "보장"하는 것과 같은 방식으로 예외가 없다는 것을 "보장"합니다. 언어 명세는 그런 것을 정의하지 않는다. 하지만 setjmp/longjmp가 있는데, 반환하지 않고 함수를 종료하는 데 사용할 수 있습니다. 따라서 프로그램은 원하는 경우 자체적 인 예외와 유사한 메커니즘을 구축 할 수 있으며, C 구현은 표준에 대한 확장을 정의 할 수 있습니다. –

18

일반 오래된 C는 기본적으로 예외를 실제로 지원하지 않습니다. 오류 코드

  • FALSE를 반환하고 last_error 변수 나 함수를 사용하여 반환

    • :

      당신과 같은 다른 오류 처리 전략을 사용할 수 있습니다.

    http://en.wikibooks.org/wiki/C_Programming/Error_handling을 참조하십시오.

  • 3

    C는 예외를 지원하지 않습니다. Visual Studio 또는 G ++를 사용하여 C++로 C 코드를 컴파일하고 현재 컴파일 상태인지 확인할 수 있습니다. 대부분의 C 응용 프로그램은 큰 변경없이 C++로 컴파일되므로 try ... catch 구문을 사용할 수 있습니다.

    5

    MSVC에서 승리하면 _try ... __except ...가 발생하지만 실제로는 끔찍한 일이므로 피할 수 있으면 사용하지 않는 것이 좋습니다. 예외가 없다는 것이 더 나을 것입니다.

    +0

    사실 C++ 예외는 SEH 상단에도 너무 적습니다. – Calmarius

    25

    setjmp.h에 정의 된 setjmp()longjmp() 함수의 조합을 사용할 수 있습니다. Example from Wikipedia

    #include <stdio.h> 
    #include <setjmp.h> 
    
    static jmp_buf buf; 
    
    void second(void) { 
        printf("second\n");   // prints 
        longjmp(buf,1);    // jumps back to where setjmp 
               // was called - making setjmp now return 1 
    } 
    
    void first(void) { 
        second(); 
        printf("first\n");   // does not print 
    } 
    
    int main() { 
        if (! setjmp(buf)) { 
         first();    // when executed, setjmp returns 0 
        } else {     // when longjmp jumps back, setjmp returns 1 
         printf("main");   // prints 
        } 
    
        return 0; 
    } 
    

    참고 : 나는 실제로 당신을 권합니다하지은 C++와 함께 끔찍한 일로 사용하기 (로컬 객체의 소멸자가 호출되지 것입니다) 그리고 무슨 일이 일어나고 있는지 이해하는 것이 정말 어렵다 에. 대신에 어떤 종류의 오류를 반환하십시오.

    +0

    예외가 사용되었을 때 파괴가 필요한 객체가없는 경우에도 setjump/longjump가 C++ 프로그램에서 올바르게 작동하지 않습니다. 나는 C 프로그램에서 거의 사용하지 않는다. – nategoose

    +0

    이것은 setjmp를 사용하는 흥미로운 접근 방법입니다. http://www.on-time.com/ddj0011.htm 그렇지만 기본적으로 스택을 풀지 않고 대역 외 코드 실행을 원할 경우 직접 작성해야합니다. –

    +0

    질문이 C 및 C++에 대한 것이 어쨌든 예외가있는 경우 C++에서 사용하는 것에 대한주의 사항이 확실하지 않습니다. 어쨌든, OP가 setjmp/longjmp 구현을 유지하여 발을 쏠 수 없다는 것을 알고 있어야합니다. 항상 *** 먼저 *** 오류 처리기를 방문해야합니다 (설정해야합니다.) 오류 처리기를 두 번 반환해야합니다. –

    14

    내장 된 예외 메커니즘이 C에 없습니다. 당신은 예외와 그 의미를 시뮬레이트해야합니다. 이것은 보통 setjmplongjmp에 의존하여 이루어집니다.

    라이브러리가 상당수 있습니다. 아직 또 다른 라이브러리를 구현 중입니다. 그것은 exceptions4c이라고 불립니다. 휴대용이며 무료입니다. 당신은 그것을보고, other alternatives과 비교해 가장 적합한 것을 볼 수 있습니다.

    +0

    도서관에 대한 링크를 제공하기 위해 +1하고 ** 대안에 대한 링크를 ** 표시합니다. – Barzee

    5

    이 질문은 매우 오래된 질문이지만, 나는 그것을 우연히 발견했고 기술을 공유 할 것이라고 생각했습니다. 즉, 0으로 나누거나 null 포인터를 역 참조하십시오.

    질문은 단순히 "어떻게 던지기"인지, 잡는 방법이 아니며, 심지어 특정 유형의 예외를 던지기위한 것입니다. 우리가 C에서 예외를 발생시켜 C++에서 잡힐 필요가 있었던 몇 년 전에 상황이있었습니다. 특히, 우리는 때때로 "순수 가상 함수 호출"오류를보고하고 C 런타임의 _purecall 함수가 무언가를 던져주도록 설득해야했습니다. 그래서 우리는 0으로 나눈 값을 가진 우리 자신의 _purecall 함수를 추가했습니다. 그리고 붐 (boom), 우리는 C++을 붙잡을 수있는 예외가있었습니다. 그리고 스택 재미를 사용하여 어떤 일이 잘못되었는지 보았습니다.

    3

    많은 스레드에서 언급했듯이이 작업을 수행하는 "표준"방법은 setjmp/longjmp를 사용하는 것입니다. https://github.com/psevon/exceptions-and-raii-in-c 할당 된 리소스의 자동 정리에 의존하는 유일한 솔루션입니다. 고유하고 공유 된 스마트 포인터를 구현하고 중간 기능을 통해 예외를 catch하지 않고 통과시키고 로컬로 할당 된 리소스를 적절히 정리할 수 있습니다.

    8

    C는 C++ 예외를 throw 할 수 있지만 어쨌든 기계어 코드입니다. a.cc에

    // begin bar.c 
    #include <stdlib.h> 
    #include <stdint.h> 
    extern void *__cxa_allocate_exception(size_t thrown_size); 
    extern void __cxa_throw (void *thrown_exception, void* *tinfo, void (*dest) (void *)); 
    extern void * _ZTIl; // typeinfo of long 
    int bar1() 
    { 
        int64_t * p = (int64_t*)__cxa_allocate_exception(8); 
        *p = 1976; 
        __cxa_throw(p,&_ZTIl,0); 
        return 10; 
    } 
    // end bar.c 
    

    bar.c 예를 들면 ,

    #include <stdint.h> 
    #include <cstdio> 
    extern "C" int bar1(); 
    void foo() 
    { 
        try{ 
        bar1(); 
        }catch(int64_t x){ 
        printf("good %ld",x); 
        } 
    } 
    int main(int argc, char *argv[]) 
    { 
        foo(); 
        return 0; 
    } 
    

    gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out 
    

    출력

    good 1976 
    

    http://mentorembedded.github.io/cxx-abi/abi-eh.html 더 상세한 정보를 갖는 컴파일 약 __cxa_throw.

    이식성 여부는 확실하지 않지만 Linux에서는 'gcc-4.8.2'로 테스트합니다.

    관련 문제