printf

2012-08-29 29 views
6

के आसपास रैपर में चेतावनी से बचें मुझे अपनी छोटी सी लाइब्रेरी में एक त्रुटि रिपोर्टिंग कार्यक्षमता है जो मैं लिख रहा हूं। मैं आसानी से त्रुटि संदेशों में एम्बेडिंग जानकारी को अनुमति देने के लिए सादा error फ़ंक्शन के अलावा errorf फ़ंक्शन प्रदान करना चाहता हूं।printf

/* 
* Prints a formatted error message. Use it as you would use 'printf'. See the 
* 'sio_error' function. 
*/ 
void sio_errorf(const char *format, ...) { 
    // Print the error prefix       
    if (g_input == STDIN) fputs("error: ", stderr); 
    else fprintf(stderr, "%s: ", g_progname); 

    // Pass on the varargs on to 'vfprintf'. 
    va_list arglist; 
    va_start(arglist, format); 
    // This may produce the following warning -- ignore it: 
    //  warning: format string is not a string literal 
    vfprintf(stderr, format, arglist); 
    va_end(arglist); 
    fputc('\n', stderr); 
} 

समस्या, मैं इस चेतावनी मिलता है (बजना 4.0 के साथ संकलन -Weverything स्विच के साथ):

चेतावनी: प्रारूप स्ट्रिंग एक स्ट्रिंग शाब्दिक

मुझे समझ में क्यों नहीं है ऐसा करना बुरा होगा। क्या इस तरह की चेतावनी से छुटकारा पाने का कोई तरीका है? क्या मैं किसी भी तरह से लागू कर सकता हूं कि format तर्क sio_errorf स्ट्रिंग अक्षरशः हो, ताकि संकलक जानता है कि यह हमेशा होगा, और मैं इसे बस पास कर रहा हूं?

मुझे पता है कि मैं -Wno-format-nonliteral का उपयोग कर सकता हूं, लेकिन केवल अगर अन्य लोग इसे मैन्युअल रूप से संकलित करने जा रहे हैं, तो वे ऐसा नहीं करेंगे। मैं स्रोत कोड में कुछ ऐसा चाहता हूं जो चेतावनी को शांत करता है।

आदर्श रूप में मैं अब भी अगर स्ट्रिंग मैं sio_errorfके लिए पारित चेतावनी मिलेगा वास्तव में एक शाब्दिक नहीं है, लेकिन मुझे यकीन है कि अगर संभव है नहीं कर रहा हूँ।

+1

कौन सा संकलक, और कौन-सा संस्करण है, तो आप उपयोग कर रहे हैं? –

+0

क्लैंग ('-v' मुझे" ऐप्पल क्लैंग संस्करण 4.0 "बताता है), हालांकि मुझे पूरा यकीन है कि जीसीसी एक ही चेतावनी देता है। – mk12

उत्तर

9

आप जीसीसी या उसके रिश्तेदारों में से एक का उपयोग कर रहे हैं, तो घोषणा पर एक विशेषता का प्रयास करें:

void sio_errorf(const char *format, ...) __attribute__((format(printf, 1, 2))); 

एक परिभाषा के लिए विशेषता को जोड़ने के लिए, तो आप इस का उपयोग कर सकते हैं:

__attribute__((format(printf, 1, 2))) 
    static void sio_errorf(const char *format, ...) { 
     .... 
+2

अच्छा विचार! यह विशेष रूप से इन परिस्थितियों के लिए जीसीसी द्वारा प्रदान किया जाता है। – Linuxios

+0

क्या यह हेडर में फ़ंक्शन प्रोटोटाइप पर जाता है? परिभाषा पर नहीं? – mk12

+0

@ एमके 12 आप इसे परिभाषा में भी लागू कर सकते हैं: '__attribute __ ((प्रारूप (printf, 1, 2))) स्थिर शून्य sio_errorf2 (कॉन्स char * प्रारूप, ...) {\ n ...'। लेकिन यदि विशेषता अनुवाद में दिखाई नहीं दे रही है, तो संकलक आपके प्रारूप/पैरामीटर की जांच नहीं करेगा। (उत्तर अपडेट करेगा) – justin

8

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

उम्मीद है कि कि संकलक आप इस तरह एक कार्यक्रम के बाद से उपयोग कर रहे हैं:

#include <stdio.h> 
int main (void) { 
    char *s = "xyzzy\n"; 
    printf (s); 
    return 0; 
} 

आप (यह मानते हुए आप -Wformat और -Wformat-nonliteral साथ चेतावनी सक्रिय कर दिया है) का वर्णन सटीक संदेश उत्पन्न करता है।

विशेष कमांड लाइन तर्क के लिए आप देख किया जाएगा:

-Wno-format-nonliteral 

जो उन कार्यों में गैर शाब्दिक तार के उपयोग की शिकायतों पाएगा। आप संकलन तो

#include <stdio.h> 
#pragma GCC diagnostic ignored "-Wformat-nonliteral" 
int main (void) { 
    char *s = "xyzzy\n"; 
    printf (s); 
    return 0; 
} 
#pragma GCC diagnostic warning "-Wformat-nonliteral" 

:

हालांकि, अगर आप अधिक परिष्कृत कुछ तो यह भी आप मक्खी पर अपने कोड pragmas साथ कुछ नैदानिक ​​संदेश के स्वभाव को निर्दिष्ट करने की अनुमति देता है भीतर खोजे जा रहे कि -Wformat -Wformat-nonliteral के साथ, आप चेतावनी नहीं देखेंगे, क्योंकि आपने main फ़ंक्शन के लिए उस विशेष चेतावनी को अनदेखा करने के लिए जीसीसी को बताया है।

#pragma GCC diagnostic push 
#pragma GCC diagnostic pop 

जो धक्का और निदान के राज्य पॉप जाएगा: एक की तुलना में मैं चलाने जीसीसी के

बाद के संस्करणों में निम्न विकल्प हैं। यह ऊपर दिए गए मेरे कोड में समस्याओं के आसपास आता है जहां आप त्रुटि के रूप में उस चेतावनी को कॉन्फ़िगर कर सकते हैं - मेरा दूसरा प्रागमा इसे चेतावनी में बदल देगा।

धक्का के उपयोग/पॉप की तरह कुछ के साथ अपने मूल स्वभाव को बहाली की अनुमति होगी:

#include <stdio.h> 
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wformat-nonliteral" 
int main (void) { 
    char *s = "xyzzy\n"; 
    printf (s); 
    return 0; 
} 
#pragma GCC diagnostic pop 
+0

आपके उत्तर के पहले भाग के लिए खेद है, मुझे यह उल्लेख करना चाहिए था कि मुझे पहले से ही पता है कि मैं '-नो-फॉर्मेट-नॉनलाइटरल' का उपयोग कर सकता हूं। हालांकि, मैं हर किसी को मजबूर नहीं कर सकता। मैं 'सब कुछ' के साथ संकलित करने में सक्षम हूं और कोई चेतावनी नहीं है। – mk12

+0

आपके उत्तर का दूसरा भाग ऐसा लगता है जो मैं चाहता हूं, हालांकि। मैं वर्तमान में जस्टिन के जवाब से इसकी तुलना कर रहा हूं। – mk12