C ++에서의 __FILE__, __LINE__ 및 __FUNCTION__ 사용법


158

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

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

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


LINE 은 올바른 일을해야합니다. PRETTY_FUNCTION을 포함하여 광범위하게 사용했습니다 . ... 그러나 ... 글쎄, 지금 LINE이 있는 코드를보고 있습니다. try / catch 예외 처리를위한 catch 블록에 있기 때문일 수 있습니다.
Krazy Glew

답변:


191

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

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


3
__func__C ++에서 일종의 문제입니다. C99는 기본 인수 등에 대해 아무 말도하지 않습니다 __func__.C ++에서 어떻게 동작 해야하는지 분명하지 않은 경우 .
wilhelmtell

4
@thr : 당신이 좋은 지적을하는 동안. 나는 __func__C ++이 아니라 c99에 존재 한다는 것이 분명했다 . 어쨌든, 나는 __func__C ++에서 합리적인 구현 이 맹 글링 된 이름을 초래할 것이라고 생각합니다 . 나는 컴파일러 작성자가 아니기 때문에 실제로 내 전화가 아닙니다.
Evan Teran

어떤 컴파일러가 전혀 지원하지 __FUNCTION__않습니까? 최근 gcc를 제외한 어떤 컴파일러가 이것을 매크로가 아닌 변수로 취급합니까?
분지

36
__func__이제 C ++ 11 표준입니다.
VX

38

드문 경우이지만 다른 줄을 바꾸는 것이 유용 할 수 있습니다 __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 전처리 기가 그렇게합니다.


29

참고 : 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. */
}

2
__PRETTY_FUNCTION__에 대해 알게되어 반갑습니다. 굉장히 유용하다!
Zheng Qu

8

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


29
"이 정보를 콘솔에 기록 할 수 있습니다"-또는 더 나은 방법 : 파일에 기록하여 문제가 발생하면 고객에게 정보를 보내달라고 요청할 수 있습니다.
Christoph

7

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__의 차이점은 무엇입니까?


1
<experimental/source_location>현재 GCC-9.
陈浩南

5

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


1
기르는 좋은 지적. strings유틸리티를 사용하여이 정보 를 추출하여 실행 파일에서 모든 문자열과 같은 데이터를 추출 하는 것은 쉽지 않습니다 . 압축 된 실행 파일도 추출 할 수 있습니다. 고객 사이트로 보내는 내용에 유의하십시오. 종종 경쟁사가 그렇게하지 않아도 실행 파일에 손을 댈 수 있습니다.
Marty
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.