2011-06-21 11 views
7

मैं हाल ही में एक मामले में भाग गया जहां मेरे पास एक कॉन्स सदस्य समारोह था जो एक ऑपरेशन कर रहा था और परिणाम लौटा रहा था। उदाहरण के लिए,क्या यह सुनिश्चित करने का कोई अच्छा तरीका है कि एक C++ फ़ंक्शन परिणाम अनदेखा नहीं किया जाता है?

class Foo { ... 
    Foo add(Foo const & x) const; 
} 

लेकिन किसी और अनजाने यह बुला रहा था यह this वस्तु (परिणाम अनदेखी) को अद्यतन करने गया था की तरह:

Foo a = ...; 
Foo b = ...; 
a.add(b); 

(। इस बग वास्तव में एक अपूर्ण रिफैक्टरिंग द्वारा पेश किया गया था)

क्या कोई पिछली पंक्ति किसी त्रुटि या चेतावनी को ट्रिगर करने का कोई तरीका है? अगली सबसे अच्छी बात एक रन-टाइम कैच होगी, जिसे ज्यादातर निम्न टेम्पलेट द्वारा संबोधित किया जाता है। हालांकि, यह काउंटर परिणाम द्वारा देखी गई वापसी मूल्य अनुकूलन को मारता है।

template<typename T> 
class MustTake { 
    T & obj; 
    bool took; 
public: 
    MustTake(T o) : obj(o), took(false) {} 
    ~MustTake() { if (!took) throw "not taken"; } 
    operator T&() { took = true; return obj;} 
}; 

struct Counter { 
    int n; 
    Counter() : n(0) {} 
    Counter(Counter const & c) : n(c.n+1) {} 
    ~Counter() {} 
}; 

Counter zero1() { 
    return Counter(); 
} 

MustTake<Counter> zero2() { 
    return Counter(); 
} 

int main() { 
    Counter c1 = zero1(); 
    printf("%d\n",c1.n); // prints 0 
    Counter c2 = zero2(); 
    printf("%d\n",c2.n); // prints 1 
    zero1(); // result ignored 
    zero2(); // throws 
    return 0; 
} 

मुझे लगता है मैं एक मैक्रो का उपयोग करके अक्षमता को कम कर सकते हैं लगता है तो MustTake <> केवल डिबग और जारी करने के लिए नो-सेशन है।

मैं संकलन-समय समाधान ढूंढ रहा हूं। यह असफल रहा, मैं सबसे अच्छा रन-टाइम समाधान ढूंढ रहा हूं।

+0

आप किस कंपाइलर का उपयोग कर रहे हैं? –

+0

यदि आप जीसीसी का उपयोग कर रहे हैं, तो मुझे लगता है कि इसके लिए चेतावनी सक्षम करने के लिए इसमें '-उन्यूज्ड-परिणाम' ध्वज है। – Xeo

+0

एक बेहतर विधि नाम चुनना मेरा सुझाव होगा। अगर मैं 'a.add (बी)' पढ़ता हूं तो मैं तुरंत म्यूटेटर सोचता हूं। वास्तव में क्या हो रहा है इसके आधार पर 'a.newListWithHead (बी) 'या कुछ समान है? 'Add' के रूप में संक्षिप्त नहीं है, लेकिन जोड़ना वास्तव में आप यहां क्या कर रहे हैं। – msandiford

उत्तर

8

यह जीसीसी और क्लैंग में (documentation) के लिए फ़ंक्शन विशेषताएँ हैं, लेकिन यह पोर्टेबल नहीं है MSVC।

class Foo { ... 
    __attribute__((warn_unused_result)) 
    Foo add(Foo const & x) const; 
} 

प्रलेखन कहते हैं कि यह realloc उदाहरण के लिए , पर प्रयोग किया जाता है, लेकिन यह अपने सिस्टम पर किसी भी अन्य मानक कार्यों पर प्रकट नहीं होता।

आप क्लैंग स्थिर विश्लेषक का उपयोग करने में रुचि भी ले सकते हैं, जो फ़ंक्शन कॉल में डेटा प्रवाह ट्रैक करता है और आपको बेहतर चेतावनियां दे सकता है।

+0

इसका उपयोग किया जाता है मेरे सिस्टम (डेबियन सिड) पर काफी कुछ syscalls - उदाहरण के लिए, 'पढ़ें() 'और' लिखें() '। Glibc में यह '__wur'' को परिभाषित करता है (यह निश्चित रूप से सी लाइब्रेरी का कार्यान्वयन विवरण है) – bdonlan

+0

हू, मैंने इसे 'grep' के साथ नहीं पकड़ा क्योंकि इसे '__wur की परिभाषा नहीं मिली '। –

+0

आप इसे मैक्रो के अंदर लपेटकर "पोर्टेबल बना सकते हैं" जो जांचता है कि संकलक जीसीसी या क्लैंग है या नहीं। अप्रयुक्त चर के बारे में चेतावनियां सक्षम करने के लिए एमएसवीसी के लिए कोई कंपाइलर ध्वज '/ W3' का उपयोग कर सकता है। [यहां देखें] (https://msdn.microsoft.com/en-us/library/c733d5h9.aspx)। हालांकि यह * सभी * घटनाओं के लिए सक्षम बनाता है। – rwols

7

माइक्रोसॉफ्ट कुलपति ++ के लिए, वहाँ _Check_return_ एनोटेशन है: http://msdn.microsoft.com/en-us/library/ms235402(v=VS.100).aspx

+0

क्या यह एमएसवीसी ++ 'मस्तचेक' एनोटेशन से अलग है? http://msdn.microsoft.com/en-us/library/ms182042(v=VS.90).aspx माइक्रोसॉफ्ट के एनोटेशन के दो अलग-अलग सेट क्यों हैं? – Tim

0

तो यह महत्वपूर्ण है कि एक वापसी मान एक समारोह के फोन करने वाले, टेम्पलेट dont_ignore द्वारा नजरअंदाज नहीं किया जा के रूप में

इस प्रकार से पहले इस्तेमाल किया जा सकता :

int add(int x, int y) 
{ 
    return x + y; 
} 

के बाद:

dont_ignore<int> add(int x, int y) 
{ 
    return x + y; 
} 

जब फ़ंक्शन का कॉलर वापसी मान का उपयोग नहीं करता है, तो एक अपवाद फेंक दिया जाता है। dont_ignore की परिभाषा:

template<class T> 
struct dont_ignore 
{ 
    const T  v; 
    bool  used; 

    dont_ignore(const T& v) 
     : v(v), used(false) 
    {} 

    ~dont_ignore() 
    { 
     if (!used) 
      throw std::runtime_error("return value not used"); 
    } 

    operator T() 
    { 
     used = true; 
     return v; 
    } 
}; 
+0

पीछे संदर्भ: http://zumalifeguard.wikia.com/wiki/Code_C%2B%2B_Functions_to_Prevent_Clients_Ignoring_Return_Values – zumalifeguard

संबंधित मुद्दे

 संबंधित मुद्दे