당신의 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이 널리 퍼질 때 어느 시점에서 지배적 일 것입니다.
- https://en.cppreference.com/w/cpp/utility/source_location
- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf
설명서는 다음과 같이 말합니다.
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 %의 경우 나쁜 결과가 없습니다.