2009-10-07 9 views
5

सी ++। चेतावनी स्तर 4 प्लस अतिरिक्त चेतावनियों का भार भी सक्षम है। मैं उम्मीद करता हूं कि यह चेतावनी देने के लिए कम से कम, लेकिन अधिक संभावना है कि एक कंपाइलर त्रुटि?यह संकलन क्यों/कैसे करता है? एमएस विजुअल स्टूडियो 2008 में

int printfLikeFunction(
    const int    bufferLength, 
    char * const   buffer, 
    const char * const  format, 
    ...); 

कोड उपयोग - उसमें कोई लेखन त्रुटि है::

समारोह घोषणा इस प्रकार है, हालांकि outputBuffer की ARRAY_SIZE में पारित हो जाता है, outputBuffer ही नहीं है - निश्चित रूप से यह संकलन नहीं करना चाहिए:

printfLikeFunction(ARRAY_SIZE(outputBuffer), "Format: %s, %s", arg1, arg2); 

स्पष्ट रूप से यह गलत है और एक गलती की गई है। हालांकि संकलक इसे पकड़ा जाना चाहिए था! बफर पैरामीटर एक चार-पॉइंटर होना चाहिए, और इसे एक स्ट्रिंग अक्षर दिया जा रहा है जो एक कॉन्स चार-पॉइंटर है। यह एक त्रुटि होनी चाहिए। (arg1 और arg2 (संभवतः कॉन्स) चार पॉइंटर्स हैं, इसलिए संयोग से घोषणा आउटपुट के बिना भी मेल खाती है बफर सही जगह पर है)।

रन टाइम पर, यह कोड क्रैश होता है क्योंकि यह स्ट्रिंग अक्षर में लिखने का प्रयास करता है। वहां कोई आश्चर्य की बात नहीं है, मुझे समझ में नहीं आता कि इसे संकलित करने की अनुमति कैसे थी।

(हालांकि, आकस्मिक रूप से, यह संभवतः यह है कि sprintf_s में इस फ़ंक्शन के लिए एक अलग क्रम में बफर और आकार पैरामीटर क्यों हैं - यह ऐसी त्रुटियों को स्पष्ट रूप से विफल करता है)।

उत्तर

9

सी ++ में प्री -const सी-स्टाइल कोड के साथ संगतता के लिए स्ट्रिंग अक्षर के लिए एक विशेष छिद्र है। हालांकि स्ट्रिंग अक्षर const char के सरणी हैं, फिर भी उन्हें पॉइंटर में गैर-const char में परिवर्तित किया जा सकता है।

पैराफ्रैशिंग 4.2/2 [conv.array]: एक 'संकीर्ण' स्ट्रिंग अक्षर को टाइप पॉइंटर के रावल्यू में गैर-constchar में परिवर्तित किया जा सकता है। रूपांतरण केवल तब माना जाता है जब एक स्पष्ट लक्ष्य प्रकार (उदा। एक फ़ंक्शन पैरामीटर) होता है और जब रावल्यू रूपांतरण के लिए सामान्य सामान्यता आवश्यक नहीं होती है।

यह रूपांतरण बहिष्कृत है, लेकिन अभी भी उपलब्ध है। ध्यान दें कि रूपांतरण के दौरान शाब्दिक को पॉइंटर में गैर-const char प्रकार में परिवर्तित करने की अनुमति मिलती है, फिर भी यह इस पॉइंटर के माध्यम से स्ट्रिंग अक्षर में किसी भी वर्ण को संशोधित करने का प्रयास करने के लिए अपरिभाषित व्यवहार का आह्वान करेगा।

+0

वाह। क्या पागल निर्णय है! लेकिन, हाँ, मैंने अभी मानक की जांच की है और आप बिल्कुल सही हैं। अविश्वसनीय! –

+0

आप उम्मीद करेंगे कि मानक स्टूडियो मानक की बहिष्कृत और पागल सुविधाओं का उपयोग करते समय चेतावनी जारी करेगा। –

+0

हां ... भले ही "पागलपन" व्यक्तिपरक है, बहिष्कृत नहीं है, इसलिए यह मुझे आश्चर्यचकित करता है कि इससे कोई चेतावनी उत्पन्न नहीं हुई है। –

2

मुझे याद है कि संकलक के पास एक विकल्प है जो नियंत्रित करता है कि स्ट्रिंग अक्षर का इलाज कैसे किया जाता है। डिफ़ॉल्ट रूप से मौजूदा गैर-कॉन्स्ट-सुरक्षित कोड को तोड़ने के लिए डिफ़ॉल्ट रूप से उन्हें char * के रूप में माना जाता है, लेकिन आप उन्हें const char * के रूप में व्यवहार करने के लिए बदल सकते हैं। यह उस त्रुटि को ट्रिगर करने में मदद कर सकता है जिसे आप ढूंढ रहे हैं।

(बाद में) मेरे पास इस समय एक माइक्रोसॉफ्ट कंपाइलर आसान नहीं है, लेकिन एमएसडीएन पर संदर्भ के माध्यम से मुझे ऐसा विकल्प नहीं दिख रहा है। मैं जीसीसी के बारे में सोच रहा हूं, जिसमें ऐसा विकल्प है।

+0

चार्ल्स के उत्तर को देखें (http://stackoverflow.com/questions/1530330/why-how-does-this-compile/1530469#1530469)। किसी भी संकीर्ण स्ट्रिंग से शाब्दिक 'char *' से एक बहिष्कृत रूपांतरण होता है जो पुराने कोड को संकलित करने की अनुमति देता है। आईएमओ जो एक पिटा है, क्योंकि यह किसी भी त्रुटि के बिना उपरोक्त कोड को संकलित करने की अनुमति देता है, लेकिन यह वही तरीका है। – sbi

+0

दिलचस्प, धन्यवाद! –

1

पूर्णांक printfLikeFunction ( स्थिरांक पूर्णांक bufferLength, चार * स्थिरांक बफर, स्थिरांक चार * स्थिरांक प्रारूप, ...);

बफर पैरामीटर char * const के रूप में निर्दिष्ट किया गया है, इसलिए यह बफर सामग्री को संशोधित करने के लिए केवल बफर पते को संशोधित करता है, बफर सामग्री नहीं।

बफर से बचने के लिए, आपको प्रारूप की तरह कॉन्स्ट char * const के रूप में घोषित करने की आवश्यकता है।

संकलक बफर में लिखने की अनुमति देता है क्योंकि आप इसे char * के रूप में घोषित करते हैं। कॉन्स्ट पोस्टफिक्स संशोधक केवल आपके फ़ंक्शन में बफर मान को पुन: असाइन करने से रोकता है।

चर पर स्थिरांक संशोधक प्रभाव देखने के लिए सी में

+1

मुझे लगता है कि मुद्दा यह है कि ओपी 'बफर' पैरामीटर को पास करने के लिए भूल गया है, और 'प्रारूप' पैरामीटर को 'बफर' के रूप में क्या लिया जाना चाहिए। – dave4420

+0

मुझे लगता है कि बफर को संशोधित करने के लिए है, यह वह जगह है जहां आउटपुट स्ट्रिंग लिखी जाएगी। यहां मुद्दा यह है कि स्ट्रिंग अक्षर को चार * के रूप में माना जाता है जबकि इसे एक कॉन्स चार * के रूप में माना जाना चाहिए। –

+0

मैं बफर संशोधित किया जाना है और बफर पैरामीटर मान के रूप में एक शाब्दिक स्थिरता पारित की जाती है, मेमोरी भ्रष्टाचार होगा क्योंकि संकलक स्मृति में एक निश्चित पते पर शाब्दिक रखेगा। – dweeves

1

स्ट्रिंग शाब्दिक वर्ण const करने के लिए (const char* const) स्थिरांक चार संकेत (char*const), नहीं स्थिरांक संकेत दिए गए हैं http://jriddell.org/const-in-cpp.html देखते हैं।

सी ++ मूल रूप से सी उपयोग का पालन किया, लेकिन फिर एएनएसआई सी ++ मानक को किसी बिंदु पर संशोधित किया गया था (मुझे यकीन नहीं है कि) उन्हें const char* const बनाने के लिए।माइक्रोसॉफ्ट उत्पादों ने परंपरागत रूप से अनुपालन पर पिछले संस्करणों के साथ पिछड़ा संगतता मानने का प्रयास किया है - "नया" व्यवहार को मजबूर करने के लिए एक कंपाइलर विकल्प हो सकता है, लेकिन चूंकि एमएसडीएन पर स्ट्रिंग अक्षर के उदाहरण सभी गैर-आधार हैं, मुझे संदेह है कि वहां है।

+2

दरअसल, सी ++ में, संकीर्ण स्ट्रिंग अक्षर प्रकार 'const char []' प्रकार के होते हैं, जो कि 'कॉन्स्ट char *' में स्पष्ट रूप से परिवर्तनीय है। चार्ल्स ने समझाया, हालांकि, 'char *' में एक बहिष्कृत रूपांतरण है। – sbi

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