2010-04-21 4 views
2

C++ 예외 클래스 작성 중 (C++에서 예외 발생을 C API를 통해 다른 언어로 전달할 수 있음).C++ 사용자 정의 예외 : 런타임 성능 및 C++에서 C로 예외 전달 (오류 정보)

//C++ 
myClass 
{ 
public: 
    myClass(); 
    ~myClass(); 

    void foo() // throws myException 
    int foo(const int i, const bool b) // throws myException 
} * myClassPtr; 


// C API 
#ifdef __cplusplus 
extern "C" { 
#endif 

myClassPtr MyClass_New(); 
void MyClass_Destroy(myClassPtr p); 
void MyClass_Foo(myClassPtr p); 
int MyClass_FooBar(myClassPtr p, int i, bool b); 

#ifdef __cplusplus 
}; 
#endif 

은 내가 C 측에 C++ 코드에서 발생한 예외를 통과 할 수있는 방법이 필요합니다 다음과 같이 공격

내 초기 계획은 진행하는 것이 었습니다. C 측에 전달하고자하는 정보는 다음과 같습니다.

(a). 무엇 (b). Where (c). 간단한 스택 추적 (발생한 순서대로 오류 메시지 시퀀스, 디버깅 정보 없음)

API 함수가 예외를 포함하는 구조체 ExceptionInfo에 대한 포인터를 갖도록 C API를 수정하고 싶습니다. info (예외가 발생했을 경우) 호출의 결과를 소비하기 전에 이 같은

그래서 C의 API에 노출 C++ 방법이 구현 될 것 인 무엇인가 :

// 내가 구현 (옆 유지 보수 악몽) 이런 종류의에 대한 미치 'hackish'뭔가가 인정해야 - THER이어야합니다 더 나은 방법? 는 C API에 노출 된 C++ 각 방법의

// ExceptionInfo default ctor initialized to no error 

void MyClass::foobarTrappedExceptionWrapper(ExceptionInfo& ei) 
{  
    try { 
     // call foobar ... 
     foobar(); 
    } 
    catch(fast_exception& fe) 
    { 
     switch (fe.errcode()) 
     { 
      //package exception info into ei for C consumption 
     } 
    } 
    catch(std::exception &e) 
    {  
     //package exception info into ei for C consumption 
    } 
} 

구현 (조각 위에 참조) 시도/catch 문에 동봉 될 필요가있다. 이에 대한 성능에 영향 (이 article에 따라) 매우 심각한 것 :

은 "그것은 실수 (높은 런타임 비용) 이벤트 자주 발생하는 이벤트 또는 에 대한 처리 C++ 예외를 사용하는 탐지 지점 근처에서 처리됩니다. " 동시에

, 나는 예외가 실제로 발생했을 때 모든 예외 처리 비용이 있지만, 그것은 비싼 becmes, 내 C++ 일 어딘가에서 읽은 기억한다. 그래서, 맞습니까? 어떻게해야합니까? 오류를 안전하게 트랩하고 결과 오류 정보를 C API에 전달할 수있는 다른 방법이 있습니까? 또는이 사소한 고려 사항입니다 (결국 기사, 꽤 오래된 하드웨어가 그 이후로 조금 향상되었습니다).

나는 간단한 스택 추적 here를 생성하는 방법을 발견 이후 [편집]

제거 question2.

+0

체크 표시를 사용하여 이전 질문에 대한 대답을 수락하는 것을 잊지 마십시오. 자세한 내용은 * "여기에 질문하는 방법"*을 참조하십시오. 또한 유용한 답변에 투표하는 것을 잊지 마십시오. 여기가 가장 기본적인 답변입니다. –

답변

2


  1. 이 모두 올바른 답변; 당신은 첫 번째 출처를 오해하고 있습니다. try {} 블록은 기본적으로 비용이 들지 않습니다. 그것은 비싸 던 던져 잡기 (즉 전파)입니다. 그래서 예외가 발생하지 않는다면 값이 싸기 때문에 자주 발생하는 경우에는 사용해서는 안됩니다 (그 이유는 자주 catch합니다 ...).
  2. 매우 길지만 고정 크기의 버퍼를 사용하면 std :: string을 사용할 때보 다 가벼워지지 않습니다. std :: string을 사용하는 것은 메모리 부족으로 인해 예외를 throw 할 수 있다고 생각하는 경우에만 나쁜 생각입니다 (이 경우 std :: string 생성자는 공간을 할당 할 수 없기 때문에 throw합니다).그러나, 왜 바퀴를 다시 발명합니까? 예외 오브젝트에 임의의 메타 데이터를 첨부 할 수있는 boost :: exception 클래스를 제공하는 boost::exception을 살펴 보시고, 가벼운 무게 (메타 데이터가 첨부되지 않음) 또는 원하는만큼 무거운 중량이 될 수 있습니다 당신이 사용하는 메타 데이터. 표준 : : 예외를 상속하는 상속 또는하지 C
    에 주변의 선택을 C++ 예외 전달에

코멘트 성능에 의미가 없습니다; 이 기사에서는 예외를 전파하고 스택 풀기를 수행하는 것이 예외 유형에 관계없이 비용이 많이 든다는 사실을 언급했습니다. C에서 오류를 넘겨주는 것에 관해서는 일반적으로 정수 반환 유형과 오류 코드를 사용하여 예외를 전달하지만 C++ 객체를 전달하려는 경우에도 마찬가지입니다. 그런 다음 다형성으로 복사 할 수있는 경우 예외 유형이면 간단히 힙에 복사본을 생성 한 다음 예외 객체를 void * 유형으로 전달할 수 있으며 해당 객체에서 정보를 추출해야하는 경우 구현 된 C 인터페이스를 만들 수 있습니다. C++을 사용하고 void * 개체를 예외 유형에 대한 포인터로 캐스팅하고 적절한 필드를 추출합니다. 만약 당신이 원하는 것이 있다면 what() 메시지는 메시지의 strdup()를 전달하는 것입니다. 그러나 할당/복사가 필요한 것은 std :: bad_alloc이 처리의 예외 중 하나라면 작동하지 않을 것이라는 것을 명심하십시오 (즉, 메모리 부족으로 인해 실패 할 수있는 경우 더 많은 메모리를 할당합니다. 좋은 생각이 아닙니다.)

"로마에있을 때 로마인처럼 행동하십시오.".... 내 자신의 충고는 C에서 반환 상태 코드와 오류 코드를 사용하고 C++에서 예외 처리를 사용하는 것입니다. 나는 C++ 예외 객체를 C 세계로 가져 오려고 애 쓰지 않을 것이다. 또한 C++ 코드가 C 코드를 호출하는 것이 C 코드를 호출하는 것이 C++ 코드로 호출하는 것이 더 일반적이라는 것을 명심하십시오. C++ 코드 용 C 인터레이스를 작성하는 경우, C 인터페이스 (즉, 오류 상태 코드 리턴)처럼 작동해야합니다. C++ 코드가 오류 상태 코드를 반환하는 C 함수를 호출하는 경우 기본 C 코드가 실패한 오류 상태 코드를 반환하는 대신 예외를 throw하는 것이 타당합니다. 이 경우에도 C++ 공간에 있으므로 C 코드로 넘어가는 예외에 대해 실제로 걱정할 필요가 없습니다. 그러나 C 언어로 교차하는 경우에는 정보를 기록하고 오류 상태 코드를 사용하는 것이 좋습니다.

std :: exception :: what()은 예외를 나타내는 정수 코드를 반환하는 반면 실제로 발생한 문제를 설명하는 char * 객체를 반환한다고 가정하면이 작업은 실제로 다른 코드를 사용하는 사람들. switch 문에서 waht()를 사용하는 것을 보았을 때 문자열을 바꿀 수 없다고 말한 다음 이중 테이크를 만들어 평소와 다른 의미를 가졌음을 알았습니다.

+0

@mike : boost :: exception에 대해 고마워, 나는 그것을 보게 될 것이다. (아마도 다른 프로젝트를 위해). 내가하는 일에 대한 좀 더 자세한 정보는 C++ 라이브러리를 모노로 노출하는 것입니다. C API는 P/Invoke에 필요합니다. 나는 C# API에 C++ 예외를 전파하는 것과 관련된 주요 문제를 해결할 것이기 때문에 모든 질문에 대한 정보를 덤프하고 싶지 않습니다. – skyeagle

+0

@mike : 국제 대회에 집착하지 않는 것에 대해 지적했다. 나는 코드를 명확히 할 것이다. – skyeagle