2010-08-13 4 views
5

를 감지 형성 함수 호출 쌍. 이는 중요한 섹션 진입 및 퇴장시 특히 중요합니다.어떻게 중첩 방식으로 정렬 함수 호출 쌍을 감지 할 수있는 도구를 찾고 올바른 함수 호출 쌍

+0

'f'에서 돌아 오기 전에 'f'에서 'g'를 호출하지 않는 이유는 무엇입니까? – Chubsdad

+0

@chubsdad :'f()'와'g()'사이에 코드가 있기 때문에 아마도'f()'와'g()'대신에'lock()'과'unlock()'을 생각할 것입니다. – caf

답변

11

C++에서 한 가지 옵션은 클래스의 생성자와 소멸자에 f()g()의 호출을 래핑하고 해당 클래스의 인스턴스를 인스턴스화하여 해당 함수를 호출하는 것입니다. 예를 들어,

struct FAndGCaller 
{ 
    FAndGCaller() { f(); } 
    ~FAndGCaller() { g(); } 
}; 

은 다음과 같이 어떤 범위 블록에서 사용할 수 있습니다

은 물론 실제 코드에서
{ 
    FAndGCaller call_f_then_later_g; // calls f() 

} // calls g() 

좀 더 적절하게 사물의 이름을 싶어, 종종 당신은 간단하게 할 것 별도의 함수가 아닌 생성자 및 소멸자 본문에 f()g()의 내용을 포함해야합니다.

범위 바인딩 된 리소스 관리 (SBRM, 또는 더 일반적으로 리소스 획득은 RAII라고도 함)의 관용구는 매우 일반적입니다.

+0

f()가 오류를 throw하면 g()는 호출되지 않지만 클래스/struct의 리소스는 해제됩니다. –

+1

@ PC2st : 참이지만'g()'가'f()'가하는 것과 반대 (또는 "undoes") 할 경우'f()'가 예외를 던지면'g()'. –

0

f()의 호출이 나타날 때마다 코드를 스캔하여 카운터를 증가시킵니다. g()의 호출을 볼 때마다 카운터를 감소시킵니다. 결국 카운터는 0으로 돌아갑니다. 음수가되면 문제가되는 것입니다 (g()에 대한 호출이 있으며이 앞에는 f()과 일치하는 호출이 없습니다).

C 및 (특히) C++의 경우 소스 코드를 이해하기위한 코드 작성은 매우 어렵습니다.은 어렵습니다. 근심, 나는이 특정 직업을위한 기존 도구에 대해 모른다. 의심 할 여지없이 clang (한 가지 예를 들어)에서 그렇게 할 수는 있지만, 완전히 혼자서하는 것보다 훨씬 쉬울 지 모르지만 여전히 사소하지는 않습니다.

+0

이 접근법의 문제점은'f()'와'g()'의 레벨을 검사하지 않는다는 것입니다. 올바른 양을 가지고 있는지 확인하지만, 당신은 그들이 같은 레벨에서 서로를 미러링하게합니다. 또한, OP는 코드를 보는 방식이 아닌 사용 도구를 요구했습니다. –

+0

@ adam_0 : 최소한 그가 보여준 코드를 기반으로, 레벨은'f()'와'g()'호출에 의해 정의됩니다. 그보다 더 많은 것이 있다면 그는 의미있는 대답을 얻는 것이 무엇인지 말해 줄 필요가있을 것입니다. 그가 원하는 것을 정확히 수행 할 수있는 기존 도구가있는 것은 의심 스럽습니다. 따라서이 도구를 작성하는 방법을 알려 주려고합니다. –

+0

clang 외에도 Qt-Creator와 함께 제공되는 Nokia의 C++ 파서 라이브러리를 사용하는 것이 좋습니다. 그것은 크로스 플랫폼이며 자체 포함되어 있습니다 (libCPlusPlus. (so, dll)). 시작하기가 너무 어렵지는 않지만, 아직까지는 그렇게 쉽지 않습니다. 그것은 그것의 많은 다른 프로젝트에서 사용 되었기 때문에 꽤 잘 쓰여지고 잘 지원됩니다. –

2

당신은 이것을 위해 for -loop을 남용 할 수 있습니다.

#define SAVETHEDAY for (bool seen = ((void)f(), true); seen; seen = ((void)g(), false)) 

쉼표 연산자는 항상 기능 나중에 g을 종속 문 앞에 실행 할 f 수 있습니다. 예컨대

SAVETHEDAY { 

    SAVETHEDAY { 

    } 
} 

장점 :

  • 중첩 수준이 명확 만듭니다.
  • C++ 및 C99에서 작동합니다.
  • pseudo for -loop은 임의의 적당한 컴파일러로 최적화 된 입니다.

단점 : 당신은 블록 내부 break, returncontinue 과 놀라움이있을 수 있습니다

  • , 그래서 g는 이러한 상황에서 호출되지 않을 수 있습니다. C++에 대한
  • 이 다시 g이 언어를 확장 일종의 때문에
  • 많은 사람들이 눈살을 찌푸리게 할 것인가라는되지 않을 수 있습니다 내부 throw에 대한 안전하지 않습니다.
  • 많은 사람들, 특히 C에 대한 ++ 코드를 숨길 일반적으로 같은 매크로 이후 으로 눈살을 찌푸리게 할 것인가는 continue의 문제는 좀 더 영리하게 일을 복구 할 수

악으로 생각된다. 처음 두 가지 단점은 더미 형식을 for -variable로 사용하여 C++에서 우회하여 생성자와 소멸자에 fg이 있습니다.

+0

놀랍게도 식칼이지만 그렇게 쓸모가 없다. – Joshua

+1

@ Joshua : 내 영어는 * cleaver *가 오타이거나 단지 더 깊은 의미를 지니고 있는지 알기에 충분하지 않을 것이다. 하지만 어쨌든, 필자가 "매일"사용하기 때문에 나에게 쓸모가없는 것은 아닙니다. 예를 들어 임계 영역을 보호하거나 일부 초기화 코드가 정확히 한 번 실행되도록하는 것은 매우 편리한 숙어입니다. –

+0

그냥 오타입니다.나는 종종 그렇게한다. – Joshua

0

Coccinelle C 코드의 의미 검색 및 패치 도구는 이러한 종류의 작업을 위해 설계되었습니다 (도구의 this LWN article 참조).