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


110

नवीनतम Xcode 3.2.1 और स्नो लेपर्ड के उन्नयन के बाद से, मुझे चेतावनी मिल रही है

"प्रारूप एक स्ट्रिंग शाब्दिक और कोई प्रारूप तर्क नहीं"

निम्नलिखित कोड से:

NSError *error = nil;

if (![self.managedObjectContext save:&error]) 
{
    NSLog([NSString stringWithFormat:@"%@ %@, %@", 
       errorMsgFormat, 
       error, 
       [error userInfo]]);      

}

तो errorMsgFormatएक है NSStringप्रारूप विनिर्देशक साथ (जैसे: "print me like this: %@"), इसके बाद के संस्करण के साथ गलत क्या है NSLogकॉल? और इसे ठीक करने के लिए अनुशंसित तरीका क्या है ताकि चेतावनी उत्पन्न न हो?

जवाबों:


113

क्या आप अपने ब्रैकेट्स को सही तरीके से नस्ट कर रहे हैं? मुझे नहीं लगता कि NSLog()केवल एक तर्क लेना पसंद करता है, जो आप इसे पारित कर रहे हैं। इसके अलावा, यह पहले से ही आपके लिए प्रारूपण करता है। ऐसा क्यों नहीं करते?

NSLog(@"%@ %@, %@", 
   errorMsgFormat, 
   error, 
   [error userInfo]);              

या, चूंकि आप कहते हैं कि errorMsgFormatएक एकल प्लेसहोल्डर के साथ एक प्रारूप स्ट्रिंग है, क्या आप ऐसा करने की कोशिश कर रहे हैं?

NSLog(@"%@, %@", [NSString stringWithFormat:errorMsgFormat, error], 
   [error userInfo]);              

14
"मुझे नहीं लगता कि NSLog () को केवल एक तर्क लेना पसंद है" NSLog()एक तर्क ले सकता है, जब प्रारूप स्ट्रिंग में कोई प्रारूप निर्दिष्टकर्ता नहीं है।
user102008

एक और चेतावनी देता है डेटा तर्क प्रारूप स्ट्रिंग द्वारा उपयोग नहीं किया जाता है।
हसन

157

Xcode शिकायत कर रहा है क्योंकि यह एक सुरक्षा समस्या है।

यहाँ कोड आपके जैसा है:

NSString *nameFormat = @"%@ %@";
NSString *firstName = @"Jon";
NSString *lastName = @"Hess %@";
NSString *name = [NSString stringWithFormat:nameFormat, firstName, lastName];
NSLog(name);

पिछले NSLog बयान इस के बराबर निष्पादित करने जा रहा है:

NSLog(@"Jon Hess %@");

यही कारण है कि NSLog एक और स्ट्रिंग तर्क की तलाश में है, लेकिन एक नहीं है। सी भाषा के काम करने के तरीके के कारण, यह स्टैक से कुछ यादृच्छिक कचरा सूचक लेने जा रहा है और इसे एनएसएसट्रिंग की तरह व्यवहार करने की कोशिश करता है। यह सबसे अधिक संभावना आपके प्रोग्राम को क्रैश करेगा। अब आपके तार में शायद उनके पास% @ नहीं है, लेकिन किसी दिन वे हो सकते हैं। आपको हमेशा डेटा के साथ एक प्रारूप स्ट्रिंग का उपयोग करना चाहिए जिसे आप स्पष्ट रूप से उन फ़ंक्शन के लिए पहले तर्क के रूप में नियंत्रित करते हैं जो प्रारूप स्ट्रिंग्स (प्रिंटफ, स्कैनफ, NSLog, - [NSString stringWithFormat:], ...) को लेते हैं।

जैसा कि ओटो बताते हैं, आपको शायद कुछ ऐसा करना चाहिए:

NSLog(errorMsgFormat, error, [error userInfo]);

17
और एसओ पर एक बार फिर, विस्तृत और अच्छे उत्तर रास्ते में आते हैं। यह पूरी तरह से समझाने के लिए धन्यवाद। मुझे यह कभी पता नहीं चला।
डैन रोसेनस्टार्क

38

अंतिम उत्तर: जैसा कि जॉन हेस ने कहा, यह एक सुरक्षा मुद्दा है क्योंकि आप एक फ़ंक्शन स्ट्रिंग को प्रारूप स्ट्रिंग की अपेक्षा कर रहे हैं। यही है, यह जो भी स्ट्रिंग के बिना सभी प्रारूप निर्दिष्टकर्ताओं का मूल्यांकन करेंगे। अगर कोई भी नहीं है, भयानक, लेकिन अगर वहाँ हैं, तो बुरी चीजें हो सकती हैं।

फिर, उचित बात यह है कि उदाहरण के लिए सीधे एक प्रारूप स्ट्रिंग का उपयोग करें

NSLog(@"%@", myNSString);

इस तरह, भले ही myNSString में प्रारूप विनिर्देशक हों, उन्हें NSLog द्वारा मूल्यांकन नहीं मिलता है।


13

मैं विशेष रूप से इसका उपयोग करने की सलाह नहीं देता, क्योंकि चेतावनी वास्तविक चेतावनी है .. भाषा के एक गतिशील उपयोग में स्ट्रिंग के लिए चीजों को रनटाइम करना संभव है (यानी नई जानकारी डालें या प्रोग्राम को क्रैश भी करें) .. हालांकि यह संभव है यदि आप जानते हैं कि यह इस तरह से होना चाहिए और आप वास्तव में इसके बारे में चेतावनी नहीं देना चाहते हैं तो दबाने के लिए मजबूर करने के लिए।

#pragma GCC diagnostic ignored "-Wformat-security"

बता दें कि GCC अस्थायी रूप से संकलन चेतावनी को नजरअंदाज कर देगा .. फिर यह कुछ भी हल नहीं कर रहा है, लेकिन कई बार ऐसा हो सकता है जब आप वास्तव में समस्या को ठीक करने का एक अच्छा तरीका नहीं ढूंढ सकते हैं।

EDIT: क्लैंग के रूप में, प्रागम बदल गया है। इसे देखें: https://stackoverflow.com/a/17322337/3937


10

इसे ठीक करने का सबसे तेज़ तरीका यह होगा कि आप @"%@",अपने NSLogकॉल में पहले तर्क के रूप में जोड़ें ,

NSLog(@"%@", [NSString stringWithFormat: ....]);

हालांकि, आपको शायद सोलह ओटो के जवाब पर विचार करना चाहिए।


10

मैं सिर्फ चेतावनी को नकारने के लिए एक शून्य से गुजर रहा हूं, शायद यह आपके लिए काम करेगा?

NSLog (myString, nil);


5
क्या कोई समझा सकता है कि एनआईएल पास होने के बाद दूसरे पैरेंट की चेतावनी को क्यों हल करता है?
1

1
पासिंग निल स्पष्ट है जबकि दूसरे पैरामीटर की कमी नहीं है। आप यह मान सकते हैं कि जब आप घर से बाहर निकले थे तो आपकी चिमनी नहीं जलाई गई थी या आप यह सुनिश्चित कर सकते हैं कि यह नहीं था। जबकि आमतौर पर कुछ भी नहीं होता है क्योंकि आप शायद ही कभी अपने फायरप्लेस का उपयोग करते हैं, यह वह समय होगा जब यह होगा कि आपका घर जल जाए।

1
@SoldOutActivist बेवजह। यहाँ गैर-स्पष्ट बिंदु (वह व्यक्ति जो C पृष्ठभूमि से नहीं आता है) वह है जो व्यवहार में अंतर स्पष्ट शून्य से गुजरने और कुछ भी नहीं पारित करने के बीच है, और आपकी टिप्पणी यह ​​स्पष्ट नहीं करती है।
मार्क एमी जूल

ललित: कुछ भी आब्ज-सी विधि जो एक चर संख्या के तर्कों को स्वीकार कर सकती है, को स्पष्ट रूप से शून्य-समाप्त किया जाना चाहिए। कुछ भी पास करना शून्य पास करने के समान नहीं है। किसी भी समय ओबज-सी के साथ बिताएं और आप इसे बार-बार देखेंगे। भवन सरणियाँ सबसे आम हैं।

3
यह संकलक चेतावनी को रोक सकता है, लेकिन अंतर्निहित समस्या, जिसे जॉन हेस द्वारा समझाया गया था , अभी भी मौजूद है - यदि एक से अधिक प्रारूप विनिर्देशक हैं myString, तो पहला ठीक होगा, लेकिन दूसरा स्टैक से कचरा उठाएगा। में प्रतिस्थापन सूची कभीNSLog() भी नहीं है nil , @ बंद। यह पता लगाने के लिए दो विकल्प हैं कि तर्कों की सूची कितनी लंबी है: एक प्रहरी मूल्य, या इसमें printf()और परिवार में क्या उपयोग किया जाता है - एक और तर्क जो संख्या की गणना की अनुमति देता है (जैसे, प्रारूप विनिर्देशकों की गिनती करके)।
jscs

3

यदि आप एक बार और सभी के लिए "एक स्ट्रिंग शाब्दिक और कोई प्रारूप तर्क नहीं" प्रारूप से चेतावनी से छुटकारा चाहते हैं, तो आप अपने लक्ष्य की निर्माण सेटिंग में GCC चेतावनी सेटिंग "टाइपचेक कॉल को प्रिंट / स्कैन करें" (GCC_WARN_TYECECECK_CALLS_TO_PRINTF = NO) को अक्षम कर सकते हैं।


5
यह चेतावनी को शांत कर देगा, लेकिन यह आपके आवेदन के भीतर अंतर्निहित दोष को ठीक करने के लिए कुछ भी नहीं करेगा। चेतावनी को शांत करने से आप एक संभावित बग को अनदेखा कर रहे हैं जो उपयोगकर्ता द्वारा दर्ज किए गए डेटा (या इस स्थिति में कोरडाटा द्वारा उत्पन्न त्रुटि संदेश) के आधार पर आपके एप्लिकेशन को क्रैश कर सकता है। इस प्रश्न के भीतर मौजूद कुछ अन्य उत्तरों का पालन करना बेहतर होगा कि स्रोत कोड के भीतर बग को हटा दें जिससे चेतावनी दिखाई दे।
क्रिस्टोफर फेयरबैर्न

2
सच ... इसीलिए मैंने "समाधान" के बजाय "चेतावनी से छुटकारा" पोस्ट किया।
Aldi

मैं एक ऐसे मामले में भाग गया, जहाँ utshsh Library इस कॉल को utstring_printf फ़ंक्शन पर ट्रिगर कर रहा था, इसलिए यह उन स्थितियों में उपयोगी है जहाँ चेतावनी गलत है।
alfwatt

2

NSLog () एक प्रारूप स्ट्रिंग की अपेक्षा करता है, जो पास हो रहा है वह सिर्फ एक स्ट्रिंग है। आपको stringWithFormat का उपयोग करने की आवश्यकता नहीं है: आप बस कर सकते हैं:

NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])

और इससे चेतावनी दूर हो जाएगी।


2

एफडब्ल्यूआईडब्ल्यू, यह आईफोन देव पर भी लागू होता है। मैं 3.1.3 एसडीके के खिलाफ कोडिंग कर रहा हूं, और एक ही समस्या के साथ एक ही त्रुटि हुई (NSLog () के अंदर stringWithFormat घोंसले के शिकार)। सिक्सटन और जॉन पैसे पर हैं।


0

बस किसी appendFormatको भी NSMutableString का उपयोग करने के बारे में बताएं , यह चेतावनी भी प्रकट कर सकती है कि क्या किसी फॉर्मेट में इस तरह से पास होने की कोशिश की जा सकती है:

NSMutableString *csv = [NSMutableString stringWithString:@""];
NSString *csvAddition = [NSString stringWithFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING];
[csv appendFormat:csvAddition];

तो इस चेतावनी से बचने के लिए, उपरोक्त को इस में बदलें:

NSMutableString *csv = [NSMutableString stringWithString:@""];
[csv appendFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING];

अधिक संक्षिप्त और अधिक सुरक्षित। का आनंद लें!


-2
NSLog(@"%@ %@, %@", 
       errorMsgFormat, 
       error, 
       [error userInfo]); 

1
stringWithFormatजब आप अभी कर सकते हैं तब निरर्थक का उपयोग करनाNSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
मार्क एमरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.