2014-09-12 5 views
6

strlen टर्मिनल नल कैरेक्टर से पहले वर्णों की संख्या देता है। strlen के एक कार्यान्वयन इस प्रकार दिखाई देंगे:अनियमित मानों के साथ एक स्ट्रिंग पर strlen अपरिभाषित व्यवहार है?

size_t strlen(const char * str) 
{ 
    const char *s; 
    for (s = str; *s; ++s) {} 
    return(s - str); 
} 

यह विशेष रूप से कार्यान्वयन dereferences s, जहां s अनिश्चित मूल्यों हो सकती है। यह इस के बराबर है:

int a; 
int* p = &a; 
*p; 

इसलिए उदाहरण के लिए इस (जो strlen का कारण बनता है एक गलत उत्पादन देने के लिए) करने के लिए अगर एक थे:

char buffer[10]; 
buffer[9] = '\0'; 
strlen(buffer); 

यह अपरिभाषित व्यवहार है?

+1

@ user2864740 क्या आप सुनिश्चित हैं कि स्ट्रिंग * में कुछ मूल्य होना चाहिए? क्या सी को पढ़ने-पहले-लिखने पर खुशी से दुर्घटनाग्रस्त होने की अनुमति नहीं है? – kay

उत्तर

2

मानक फ़ंक्शन को कॉल करना strlen अपरिभाषित व्यवहार का कारण बनता है। DR 451 इस स्पष्ट किया:

पुस्तकालय कार्यों अपरिभाषित व्यवहार जब अनिश्चित मूल्यों

पर इस्तेमाल किया एक और अधिक में गहराई से चर्चा see this thread के लिए प्रदर्शन करेंगे।

+0

नीचे दी गई मेरी टिप्पणी एक स्ट्रेल फ़ंक्शन के पोस्टर के कार्यान्वयन को संदर्भित करती है। सहमत हैं कि मानक पुस्तकालय में अन्य बाधाएं या स्वतंत्रताएं हैं। –

+0

बफर [9] बहुत दृढ़ संकल्प है ... – Basilevs

+0

@ केसी-एनएच ने अपनी पोस्ट को यह स्पष्ट करने के लिए अद्यतन किया कि मैं मानक 'स्ट्रेलन' फ़ंक्शन के बारे में बात कर रहा हूं, न कि ओपी के छद्म-कार्यान्वयन। –

1

नहीं, यह अपरिभाषित व्यवहार नहीं है। आपका स्ट्रेल फ़ंक्शन बफर के अंत से पहले रुक जाएगा। यदि आपके strlen फ़ंक्शन संदर्भित बफर [10], तो, हाँ, जो अपरिभाषित है।

यह निश्चित रूप से अप्रत्याशित व्यवहार होगा, क्योंकि अधिकांश बफर में यादृच्छिक डेटा होता है। "अपरिभाषित" भाषा मानकों को लिखने वाले लोगों के लिए विशेष शब्द है। इसका मतलब है कि स्मृति दोषों या कार्यक्रम से बाहर निकलने सहित कुछ भी हो सकता है। अप्रत्याशित रूप से, मेरा मतलब है कि यह सुनिश्चित नहीं है कि प्रोग्रामर क्या करना चाहता था। कुछ रनों पर, स्ट्रेल का परिणाम 3 हो सकता है या यह 10 हो सकता है।

0

हां, यह अपरिभाषित व्यवहार है।

व्यवहार निम्न परिस्थितियों में अपरिभाषित है::

...

स्वत: भंडारण अवधि के साथ एक वस्तु का मूल्य मसौदा C11 मानक, §J.2 "अपरिभाषित व्यवहार" से इसका प्रयोग अनिश्चित है।

+2

यह कोड वास्तव में अनिश्चित मानों का उपयोग नहीं करता है ('बफर 'अनिश्चित नहीं है, लेकिन' बफर [0]' है)। हालांकि, 'strlen' मानों का उपयोग करता है। इसके अलावा, यह अनुबंध गैर-मानक है (यह यूबी के विभिन्न मामलों को खोजने के लिए सूचकांक का एक प्रकार होना चाहिए)। मानक पाठ अधिक विस्तृत है और जब अनिश्चित उपयोग यूबी नहीं है तो कुछ अपवाद हैं। –

+1

ऑब्जेक्ट न केवल "अनिश्चित" है, लेकिन मान केवल "अनिर्दिष्ट" हैं, इसलिए कुछ भी बुरा नहीं हो सकता है। –

2

आपके द्वारा दिखाए जा रहे संस्करण का व्यवहार अच्छी तरह से परिभाषित किया गया है।

  • अप्रारंभीकृत सरणी के बाइट्स 10 वीं तत्व है कि आप 0 करने के लिए सेट के अपवाद के साथ, सभी अनिश्चित मान हैं।
  • एक अनिश्चित मूल्य तक पहुंच केवल यूबी होगी यदि अंतर्निहित वस्तु का पता कभी नहीं लिया जाएगा या यदि मूल्य संबंधित प्रकार के लिए एक जाल है।
  • चूंकि यह एक सरणी है और सरणी तत्वों तक पहुंच पॉइंटर अंकगणितीय के माध्यम से है, पहला मामला प्रासंगिक नहीं है, यहां।
  • किसी भी char मूल्य को यूबी के बिना एक्सेस किया जा सकता है, मानक में जाल के प्रतिनिधित्व के बारे में खंड स्पष्ट रूप से उस से सभी वर्ण प्रकारों को बाहर कर देते हैं।
  • इस प्रकार जिन मूल्यों के साथ आप काम कर रहे हैं वे बस "अनिर्दिष्ट" हैं।
  • अनिर्दिष्ट मान पढ़ना सी मानकों की समिति के कुछ सदस्यों के अनुसार हर बार अलग-अलग परिणाम दे सकता है, कुछ लोग "पूरी तरह से" राज्य कहलाते हैं या नहीं। यह संपत्ति प्रासंगिक नहीं है, यहां से, क्योंकि आपका फ़ंक्शन किसी भी समय इस तरह के मान को पढ़ता है।
  • तो सरणी तत्वों तक आपकी पहुंच आपको कोई मनमानी लेकिन वैध char मान देता है।
  • आपको यकीन है कि आपके for लूप 9 पर नवीनतम स्थिति पर बंद हो जाता है, इसलिए आप अपनी सरणी को ओवरराउन नहीं करेंगे।

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

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