C ++에서의 __FILE__, __LINE__ 및 __FUNCTION__ 사용법 __LINE__그리고 __FUNCTION__로깅 및

당신의 C ++ 컴파일러가 지원하는 그들, 특별한 이유가 있다고 가정하면 되지 사용에 __FILE__, __LINE__그리고 __FUNCTION__로깅 및 디버깅 목적은?

주로 사용자에게 잘못된 데이터 (예 : 잘못된 줄 번호 또는 기능을 최적화의 결과보고)를 제공하거나 결과적으로 성능을 저하시키는 데 관심이 있습니다.

기본적으로, 신뢰할 수있는 __FILE__, __LINE__그리고 __FUNCTION__항상 옳은 일을?



답변

__FUNCTION__비표준이며 __func__C99 / C ++ 11에 있습니다. 다른 ( __LINE____FILE__)는 괜찮습니다.

항상 올바른 파일과 행을보고합니다 ( __FUNCTION__/ 를 사용하도록 선택한 경우 기능 __func__). 최적화는 컴파일 타임 매크로 확장이기 때문에 비 인수입니다. 그것은 것입니다 결코 어떤 방식으로 성능에 영향이 없습니다.


답변

드문 경우이지만 다른 줄을 바꾸는 것이 유용 할 수 있습니다 __LINE__. GNU configure가 원본 소스 파일에 나타나지 않는 줄 사이에 부두를 삽입 한 후 일부 테스트에서 적절한 줄 번호를보고하는 것을 보았습니다. 예를 들면 다음과 같습니다.

#line 100

다음 줄을 __LINE__100으로 시작합니다 . 선택적으로 새 파일 이름을 추가 할 수 있습니다

#line 100 "file.c"

거의 유용하지 않습니다. 그러나 필요한 경우 내가 아는 대안이 없습니다. 실제로, 행 대신 매크로를 사용할 수 있으므로 위의 두 가지 형식 중 하나를 가져와야합니다. 부스트 전 처리기 라이브러리를 사용하면 현재 줄을 50 씩 증가시킬 수 있습니다.

#line BOOST_PP_ADD(__LINE__, 50)

__LINE__and 의 사용법에 대해 질문 한 이후에 언급하는 것이 유용하다고 생각했습니다 __FILE__. 하나는 C ++에서 놀라움을 충분히 얻지 못합니다 🙂

편집 : @Jonathan Leffler는 주석에 더 좋은 사용 사례를 제공합니다.

#line으로 메시지를 보내는 것은 사용자의 C 코드에보고 된 오류를 사용자의 소스 파일과 일치하게 유지하려는 프리 프로세서에 매우 유용합니다. Yacc, Lex 및 (더 많은 집에서) ESQL / C 전처리 기가 그렇게합니다.


답변

참고 : g ++는 비표준 __PRETTY_FUNCTION__ 매크로를 제공합니다. 지금까지 나는 C99 __func__에 대해 몰랐습니다 (Evans에게 감사합니다!). 여분의 클래스 범위에 사용할 수있을 때 여전히 __PRETTY_FUNCTION__을 선호한다고 생각합니다.

추신:

static string  getScopedClassMethod( string thePrettyFunction )
{
  size_t index = thePrettyFunction . find( "(" );
  if ( index == string::npos )
    return thePrettyFunction;  /* Degenerate case */

  thePrettyFunction . erase( index );

  index = thePrettyFunction . rfind( " " );
  if ( index == string::npos )
    return thePrettyFunction;  /* Degenerate case */

  thePrettyFunction . erase( 0, index + 1 );

  return thePrettyFunction;   /* The scoped class name. */
}

답변

개인적으로, 나는 디버깅 메시지 외에는 이것을 사용하는 것을 꺼려합니다. 나는 그것을했지만 고객이나 최종 사용자에게 그런 종류의 정보를 보여 주려고하지 않습니다. 내 고객은 엔지니어가 아니며 때로는 컴퓨터에 정통하지 않습니다. 이 정보를 콘솔에 기록 할 수는 있지만 디버그 빌드 또는 내부 도구를 제외하고는 마지 못해 있습니다. 나는 그것이 당신이 가진 고객 기반에 달려 있다고 생각합니다.


답변

C ++ 20 std::source_location

C ++은 마침내 매크로가 아닌 옵션을 추가했으며 C ++ 20이 널리 퍼질 때 어느 시점에서 지배적 일 것입니다.

설명서는 다음과 같이 말합니다.

constexpr const char * function_name () const noexcept;

6 반환 값 :이 객체가 함수 본문의 위치를 ​​나타내는 경우 함수 이름에 해당하는 구현 정의 NTBS를 반환합니다. 그렇지 않으면 빈 문자열을 반환합니다.

여기서 NTBS는 “Null Terminated Byte String”을 의미합니다.

지원이 GCC에 도착하면 GCC 9.1.0이 g++-9 -std=c++2a지원하지 않을 때 시도해 보겠습니다 .

https://en.cppreference.com/w/cpp/utility/source_location 클레임 사용법은 다음과 같습니다.

#include <iostream>
#include <string_view>
#include <source_location>

void log(std::string_view message,
         const std::source_location& location std::source_location::current()
) {
    std::cout << "info:"
              << location.file_name() << ":"
              << location.line() << ":"
              << location.function_name() << " "
              << message << '\n';
}

int main() {
    log("Hello world!");
}

가능한 출력 :

info:main.cpp:16:main Hello world!

__PRETTY_FUNCTION__vs __FUNCTION__vs __func__vsstd::source_location::function_name

답변 : __PRETTY_FUNCTION__, __FUNCTION__, __func__의 차이점은 무엇입니까?


답변

나는 항상 그들을 사용합니다. 내가 걱정하는 유일한 것은 로그 파일에서 IP를 제공하는 것입니다. 함수 이름이 정말 좋으면 영업 비밀을보다 쉽게 ​​찾을 수 있습니다. 디버그 기호를 사용하여 배송하는 것과 비슷하지만 찾기가 더 어렵습니다. 99.999 %의 경우 나쁜 결과가 없습니다.