문제

런타임에보고/비활성화 할 수있는 로깅 모듈을 사용하고 있습니다. 통화는 일반적으로 다음과 같은 것입니다.

WARN(
     "Danger Will Robinson! There are "
     + boost::lexical_cast<string>(minutes)
     + " minutes of oxygen left!"
);

나는 경고에 인라인 함수를 사용하고 있지만, 전체 프로그램의 논쟁 평가는 비용이 많이들 것입니다. 그만큼 WARN 기능은 다음과 같이됩니다.

bool WARNINGS_ENABLED = false;
inline void WARN(const string &message) {
    if (!WARNINGS_ENABLED) {
       return;
    }
    // ...
}

문자열 인수를 구성하면 부작용이 없다는 점에서 컴파일러가이를 최적화 할 것인가? 일정 수준의 최적화가 필요합니다 (-Ox 안에 g++ 일부 x)?

도움이 되었습니까?

해결책

런타임에 경고를 선택적으로 활성화하고 비활성화 할 수 있어야하는 경우 컴파일러는 ~ 아니다 통화를 최적화 할 수 있습니다.

필요한 것은 이름을 바꾸는 것입니다 기능 에게 WARN2 그리고 다음과 같은 매크로를 추가하십시오.

#define WARN(s) do {if (WARNINGS_ENABLED) WARN2(s);} while (false)

이렇게하면 경고가 가능하지 않으면 런타임에 S 평가를 방지 할 수 있습니다.

do-while 물건은 코드의 어느 곳에서나 사용할 수있는 트릭입니다 (알몸 진술, 브레이스 if 블록 내의 진술, 끊임없는 if 블록, 브레이스 및 비판이있는 동안 진술 등).

다른 팁

GCC/G ++를 사용하여 무엇을하는지 확인할 수 있습니다. -에스 옵션. 코드가 실제로 조립되기 전에 코드를 출력합니다. GCC (1).

이 경우 GCC 및 G ++는 동일하게 동일하게 작동합니다. 그래서 먼저 코드를 C로 번역하여 몇 가지 추가 테스트를 수행했습니다.

char WARNINGS_ENABLED = 0;

inline void WARN(const char* message) {
    if (!WARNINGS_ENABLED) {
        return;
    }
    puts(message);
}

int main() {
    WARN("foo");
    return 0;
}

운영 gcc -o3 -s file.c 출력 파일을 살펴보십시오.파일'
당신은 그 GCC를 볼 것입니다 아무것도 제거하지 않았습니다!

그것은 당신이 요청한 것이 아니라 컴파일러에게 해당 코드를 최적화 할 수있는 기회를 제공하기 위해서는 WARNINGS_ENABLED를 만들어야합니다. 끊임없는. 대안은 그것을 만드는 것입니다 공전 해당 파일 내에서 값을 변경하지 않습니다. 하지만: 그것을 만들기 공전 기호가 내보내지 않는 부작용이 있습니다.

static const char WARNINGS_ENABLED = 0;

inline void WARN(const char* message) {
  if (!WARNINGS_ENABLED) {
      return;
  }
  puts(message);
}

int main() {
    WARN("foo");
    return 0;
}

그런 다음 GCC는 코드를 완전히 정리합니다.

부작용이 없다는 것을 증명할 수 있다면 (컴파일러가 값 비싼 함수 호출을 위해하기 어려울 수 있음) 최적화 할 수있는 기회가 있다고 생각합니다.

나는 부스트 전문가가 아니지만 Warnings_enabled가 사실 인 경우 문자열을 생성하기 위해 평가 될 람다를 건설 할 수있는 방법이 있다고 생각합니다. ... 같은 ...

inline void warnFunc(some_boost_lambda &message_generator) {
  if (WARNINGS_ENABLED) {
    cerr << message_generator() << endl;
  }
}

#define WARN(msg) warnFunc(...insert boost magic here to turn msg into a lambda...)

아니요, 컴파일러가 있어야합니다 ~ 아니다 Global 경고 _enabled가 const로 선언되지 않는 한 어쨌든 코드를 최적화하십시오.

BTW, 경고가 인라인 함수 인 경우, 메시지 구성 가격 (Lexical_cast 및 Operator+ on Strings에서는 예시에서 매우 비효율적)을 지불합니다.

런타임이 비활성화 된 경우 효율적인 (최소 (분기 예측 CPU가있는 0에 가깝음) 오버 헤드)는 다음과 같습니다. 로깅 매크로 기능과 스트림 스타일 로깅을 모두 지원합니다.

사전 처리기를 사용하여 모든 것을 정의 할 수 없습니까?

void inline void LogWarning(const string &message) 
{
  //Warning
}

#ifdef WARNINGS_ENABLED
#define WARN(a) LogWarning(a)
#else
#define WARN(a)
#endif

이것은 Assert () 매크로가 작동하는 방식입니다. WARN의 괄호 안에있는 모든 코드는 전처리기를 통해 컴파일러로 만들지 않습니다. 그것은 당신이 다른 일을 할 수 있음을 의미합니다

#ifdef WARNINGS_ENABLED
// Extra setup for warning
#endif
//....
WARN(uses setup variables)

그리고 그것은 두 가지 방법을 컴파일 할 것입니다.

최적화기가 괄호 안에 부작용이 없다는 것을 깨닫게하는 것에 관해서는, 어느 쪽이든 증명하기 어려운 꽤 복잡한 진술 (예 : 높은 수준의 문자열 조작)을 넣을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top