C ++ में __FILE__, __LINE__ और __FUNCTION__ उपयोग


158

यह मानते हुए कि आपका C ++ कंपाइलर उनका समर्थन करता है, क्या कोई विशेष कारण उपयोग नहीं करना है __FILE__, __LINE__और __FUNCTION__लॉगिंग और डीबगिंग प्रयोजनों के लिए?

मैं मुख्य रूप से उपयोगकर्ता को भ्रामक डेटा देने से संबंधित हूं- उदाहरण के लिए, अनुकूलन के परिणामस्वरूप गलत लाइन नंबर या फ़ंक्शन की रिपोर्ट करना - या परिणामस्वरूप एक प्रदर्शन हिट लेना।

असल में, मैं भरोसा कर सकते हैं __FILE__, __LINE__और __FUNCTION__करने के लिए हमेशा सही काम करते हैं?


LINE को सही काम करना चाहिए। मैंने PRETTY_FUNCTION सहित बड़े पैमाने पर इसका और इसके साथियों का उपयोग किया है । ... लेकिन ... ठीक है, मैं अभी ठीक उस कोड को देख रहा हूं जहां LINE निहित है। शायद इसलिए कि यह अपवाद से निपटने की कोशिश / पकड़ के लिए एक पकड़ ब्लॉक में है।
क्रेजी ग्लीव

जवाबों:


191

__FUNCTION__गैर मानक है, __func__C99 / C ++ 11 में मौजूद है। अन्य ( __LINE__और __FILE__) अभी ठीक हैं।

यह हमेशा सही फ़ाइल और लाइन की रिपोर्ट करेगा (और यदि आप उपयोग करना चाहते हैं __FUNCTION__/ तो फ़ंक्शन __func__)। अनुकूलन एक गैर-कारक है क्योंकि यह एक संकलन समय स्थूल विस्तार है; यह किसी भी तरह से प्रदर्शन को कभी प्रभावित नहीं करेगा ।


3
__func__C ++ में एक समस्या है। C99 डिफ़ॉल्ट तर्कों और इसके बाद के मामलों के बारे में एक शब्द नहीं कहता है, जहां यह स्पष्ट नहीं है कि __func__C ++ में कैसे व्यवहार किया जाना चाहिए।
विल्हेमटेल

4
@thr: जब आप एक अच्छा बिंदु बनाते हैं। मैं बहुत स्पष्ट था कि __func__c99 में मौजूद है, c ++ नहीं। इसके बावजूद, मुझे लगता है कि __func__सी ++ में एक उचित कार्यान्वयन केवल परिणामी नाम होगा। चूंकि मैं एक संकलक लेखक नहीं हूं, यह वास्तव में मेरी कॉल नहीं है।
इवान टेरान

क्या संकलक बिल्कुल भी समर्थन नहीं करते __FUNCTION__हैं? हाल ही में जीसीसी को छोड़कर कौन से संकलक इसे चर के रूप में मानते हैं, मैक्रो नहीं?
बेसिन

36
__func__अब C ++ 11 मानक में है।
वीएक्स

38

दुर्लभ मामलों में, यह उस रेखा को बदलने के लिए उपयोगी हो सकता है जो __LINE__किसी और चीज द्वारा दी गई है। मैंने देखा है कि GNU कॉन्फ़िगर करता है कि कुछ परीक्षणों के लिए उपयुक्त लाइन नंबरों की रिपोर्ट करने के बाद यह उन लाइनों के बीच कुछ वूडू डालें जो मूल स्रोत फ़ाइलों में प्रकट नहीं होती हैं। उदाहरण के लिए:

#line 100

निम्न पंक्तियों को __LINE__100 से शुरू करेगा। आप वैकल्पिक रूप से एक नया फ़ाइल-नाम जोड़ सकते हैं

#line 100 "file.c"

यह केवल शायद ही कभी उपयोगी है। लेकिन अगर इसकी जरूरत है, तो कोई विकल्प नहीं है जो मुझे पता है। दरअसल, लाइन के बजाय, एक मैक्रो का उपयोग किया जा सकता है, जिसके परिणामस्वरूप उपरोक्त दो रूपों में से किसी एक में परिणाम होना चाहिए। बूस्ट प्रीप्रोसेसर लाइब्रेरी का उपयोग करके, आप वर्तमान लाइन को 50 से बढ़ा सकते हैं:

#line BOOST_PP_ADD(__LINE__, 50)

मैंने सोचा कि यह जब से तुम के उपयोग के बारे में पूछा यह उल्लेख करने के लिए उपयोगी है __LINE__और __FILE__। किसी को भी C ++ से पर्याप्त आश्चर्य नहीं होता है :)

संपादित करें: @ जोनाथन लेफ़लर टिप्पणियों में कुछ और अच्छे उपयोग के मामले प्रदान करते हैं:

प्री-प्रोसेसर्स के लिए #line के साथ मैसेज करना बहुत उपयोगी होता है जो यूजर के C कोड में रिपोर्ट की गई त्रुटियों को यूजर की सोर्स फाइल के अनुरूप रखना चाहते हैं। Yacc, Lex, और (मेरे लिए घर पर अधिक) ESQL / C पूर्वप्रक्रमक ऐसा करते हैं।


29

FYI करें: g ++ गैर-मानक __PRETTY_FUNCTION__ मैक्रो प्रदान करता है। अब तक मुझे C99 __func__ (धन्यवाद इवान!) के बारे में नहीं पता था। मुझे लगता है कि मैं अभी भी __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__ के बारे में जानकर अच्छा लगा। बहुत उपयोगी!
झेंग क्व

8

व्यक्तिगत रूप से, मैं कुछ भी लेकिन डीबगिंग संदेशों के लिए इनका उपयोग करने के लिए अनिच्छुक हूं। मैंने इसे किया है, लेकिन मैं कोशिश करता हूं कि ग्राहकों या अंतिम उपयोगकर्ताओं को उस तरह की जानकारी न दिखाऊं। मेरे ग्राहक इंजीनियर नहीं हैं और कभी-कभी कंप्यूटर के जानकार नहीं होते हैं। मैं इस जानकारी को कंसोल में लॉग कर सकता हूं, लेकिन, जैसा कि मैंने कहा, अनिच्छा से डिबग बिल्ड या आंतरिक टूल को छोड़कर। मुझे लगता है कि यह आपके पास ग्राहक आधार पर निर्भर करता है, हालांकि।


29
"मैं इस जानकारी को कंसोल में लॉग इन कर सकता हूं" - या बेहतर अभी तक: इसे एक फ़ाइल में लॉग इन करें ताकि अगर कुछ गलत हो जाए तो आप ग्राहक को इसे आपको भेजने के लिए कह सकें ...
Christoph

7

सी ++ 20 std::source_location

C ++ ने आखिरकार एक गैर-मैक्रो विकल्प जोड़ा है, और यह संभवतया भविष्य में किसी बिंदु पर हावी होगा जब C ++ 20 व्यापक हो जाएगा:

प्रलेखन कहता है:

constexpr const char * function_name () कांस्ट नोइसेप्ट;

6 रिटर्न: यदि यह ऑब्जेक्ट किसी फ़ंक्शन के शरीर में स्थिति का प्रतिनिधित्व करता है, तो कार्यान्वयन-परिभाषित NTBS देता है जो फ़ंक्शन नाम के अनुरूप होना चाहिए। अन्यथा, एक खाली स्ट्रिंग लौटाता है।

जहाँ NTBS का अर्थ है "शून्य समाप्त बाइट स्ट्रिंग"।

जब समर्थन जीसीसी के लिए आता है, तो मैं इसे एक कोशिश देता हूं, जीसीसी 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__बनाम __FUNCTION__बनाम __func__बनामstd::source_location::function_name

उत्तर दिया गया: __PRETTY_FUNCTION__, __FUNCTION__, __func__ के बीच क्या अंतर है?


1
नहीं है <experimental/source_location>वर्तमान जीसीसी-9 में।
陈浩南

5

मुझे उन्हें हर समय इस्तेमाल करना है। केवल एक चीज जिसके बारे में मुझे चिंता है वह लॉग फ़ाइलों में आईपी को दूर कर रही है। यदि आपके फ़ंक्शन के नाम वास्तव में अच्छे हैं, तो आप एक व्यापार रहस्य को उजागर करना आसान बना सकते हैं। यह डिबग प्रतीकों के साथ शिपिंग की तरह है, केवल चीजों को ढूंढना अधिक कठिन है। 99.999% मामलों में कुछ भी बुरा नहीं होगा।


1
ऊपर लाने के लिए अच्छी बात है। stringsनिष्पादन योग्य से सभी स्ट्रिंग-जैसे डेटा निकालने के लिए उपयोगिता का उपयोग करके इस जानकारी को निकालना तुच्छ है । यहां तक ​​कि संपीड़ित निष्पादन योग्य भी निकाले जा सकते हैं। ग्राहक साइट पर आपके द्वारा भेजे गए कार्यों से बहुत सावधान रहें। अक्सर कई बार प्रतियोगी अपने हाथों को आपके निष्पादन में प्राप्त करने में सक्षम होते हैं, भले ही वे ऐसा करने के लिए नहीं होते हैं।
मार्टी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.