2016-07-03 2 views
2

내가 작업하고있는 프로젝트에서 오류를 처리하기 위해 오류 코드 (예외 없음)를 반환하는 기능 만 사용하는 데 동의했습니다.인수 값에 따라 계기

내 코드를 디버그 메시지로 "오염시키지 않기 위해서"나는 계측에 기반한 솔루션 (this post에서 영감을 얻어)을 연구 중이었습니다. 에,

// File rc.cc 
#include <stdio.h> 
#include <time.h> 
#include "rc.h" 

static FILE *fp_trace; 
static int isError;  

extern "C" 
{ 

    void __attribute__ ((constructor)) trace_begin (void) 
    { 
     fp_trace = fopen("trace.out", "w"); 
     isError = 0; 
    } 

    void __attribute__ ((destructor)) trace_end (void) 
    { 
     if(fp_trace != NULL) { 
     fclose(fp_trace); 
     } 
    } 

    void __cyg_profile_func_enter (void *func, void *caller) __attribute__((no_instrument_function)); 
    void __cyg_profile_func_exit (void *func, void *caller) __attribute__((no_instrument_function)); 

    void __cyg_profile_func_enter (void *func, void *caller) 
    { 
    } 

    void __cyg_profile_func_exit (void *func, void *caller) 
    { 
    if ((fp_trace != NULL) && (isError == 1)) { 
     fprintf(fp_trace, "x %p %p %lu\n", func, caller, time(NULL)); 
     isError = 0; 
    } 
    } 
} 

rc::rc(int valueIn) : 
    value(valueIn) 
{ 
} 

rc& rc::operator=(rc rcIn) 
{ 
    value = rcIn.value; 
    if (value != 0) 
    { 
     isError = 1; 
     fprintf(fp_trace, "%d\n", value); 
    } 
    return *this; 
} 

그러나 :

// File rc.h 
class rc 
{ 
public: 
    rc(int) __attribute__((no_instrument_function)); 
    rc& operator=(rc); 
private: 
    int value; 
}; 

그런 다음 이러한 사업자 및 계측 기능을 정의하는 대신 오류 코드로의 int를 사용

, 나는 같은 클래스에서 캡슐화하고 있습니다 너무 많은 것을 인쇄하지 않기 위해서 return 코드 0을 반환하는 함수 호출을 기록하고 싶지 않으므로 isError 플래그를 사용하십시오.

은 다음 예제와 함께 사용할 수 있습니다

#include <cstdlib> 
#include <ctime> 
#include "rc.h" 

rc bar(void) 
{ 
    rc result(std::rand() % 3); 
    return result; 
} 

int main(void) 
{ 
    std::srand (std::time(NULL)); 
    rc returnCode(0); 
    for (int i=0; i<10; ++i) 
    { 
    returnCode = bar(); 
    } 
    return 0; 
} 

컴파일 및

g++ -finstrument-functions -g -c -o rc.o rc.cc 
g++ -g -c -o test.o test.cc 
g++ test.o rc.o -o a.out 
./a.out 

같은 것을 발생합니다 in the previously mentioned post 주어진 스크립트로 출력 읽기와 실행

Error code 2 
rc::operator=(rc) at 2016-07-03T18:32:09+0200, called from main (test.cc:32) 

이것은 거의 내가 원하는 것일 수 있습니다. 하지만 단순히 출력이 0이 아닌지 테스트하기 위해 rc foo(void)에 테스트를 추가하는 솔루션과 비교하면 오류가 발생하는 경우 오버 헤드 만 추가됩니다 (검사로 인한 오버 헤드가 추가됨). 잘하면 너무 자주는 아니지만), 나는 오버 헤드를 추가 할 예정이다. 계기 때문에 (각 RC 래퍼로 인해 가능한 오버 헤드가 더해 지지만 나는 그걸로 OK이다.) ...

해결책이 있는가? 생각하지 않으면 인수가 0 인 경우 을 계측하지 않겠습니까? rc::value은 런타임에만 알려져 있기 때문에, 나는 value=0에 대해 전문화 될 가치가있는 템플릿을 인수로 생각하지 않고 그 케이스를 조작하지 않을 것입니다. 그럴 거니?

추가 제한이 있습니다. 호출자를 알고 싶기 때문에 계측 된 함수가 대입 연산자이므로 중요한 추가 프록시 수준을 추가 할 수 없습니다.


이 지난 시점에 편집, 나는 할당 연산자 인라인을 생각 (그리고 계측) 및 반환 코드가 0이 아닌 경우에 계측 함수를 호출하지만 할 수없는 것 finstrument-function doc page은 다음과 같이 명시합니다.

이 계측은 다른 기능에서 인라인으로 확장 된 기능에 대해서도 수행됩니다. 프로파일 링 호출은 인라인 함수가 어디에서 개념적으로 입력되고 종료되는지를 나타냅니다.

그래서 진짜 호출자를 가리 키지 않았습니다.

+0

처음부터 모든 코드를 작성하고 C++ 라이브러리를 사용하지 않는다면 어쨌든 프로그램 예외가 발생할 수 있습니다. –

+0

예, 알고 있습니다. 그러나 우리는 많은 것을 다시 쓰고 있습니다 ... – Vser

+0

좋은 힌트는 음수를 오류 코드로 사용하고 결과에 양수 값 (0 포함)을 사용하는 것입니다. 이것이 바로 Linux 시스템 콜이하는 일입니다. –

답변

0

해결 방법은 계측에 의존하는 것이 아니라 계측에 사용되는 __builtin_return_address(unsigned int) 함수에 대한 것입니다.

당신은 호출자의 반환 포인터를 얻기 위해이 기능을 사용할 수 있습니다

:

rc& rc::operator=(rc rcIn) 
{ 
    value = rcIn.value; 
    if (value != 0) 
    { 
     fprintf(fp_trace, "%d %p\n", value, __builtin_return_address(1)); 
    } 
    return *this; 
} 

당신은 발신자 주소를 얻기 위해 장비에 의존 할 필요가 없습니다 및 사용을 통해 정말 약간의 오버 헤드를 추가합니다 그 방법을 단순히 int.