2009-08-11 20 views
63

संपादित करें: मैंने उदाहरण के लिए स्रोत जोड़ा है।आप strcpy के बजाय strncpy का उपयोग क्यों करना चाहिए?

मैं this example भर में आया था:

char source[MAX] = "123456789"; 
char source1[MAX] = "123456789"; 
char destination[MAX] = "abcdefg"; 
char destination1[MAX] = "abcdefg"; 
char *return_string; 
int index = 5; 

/* This is how strcpy works */ 
printf("destination is originally = '%s'\n", destination); 
return_string = strcpy(destination, source); 
printf("after strcpy, dest becomes '%s'\n\n", destination); 

/* This is how strncpy works */ 
printf("destination1 is originally = '%s'\n", destination1); 
return_string = strncpy(destination1, source1, index); 
printf("After strncpy, destination1 becomes '%s'\n", destination1); 

कौन इस उत्पादन का उत्पादन:

destination is originally = 'abcdefg' 
After strcpy, destination becomes '123456789' 

destination1 is originally = 'abcdefg' 
After strncpy, destination1 becomes '12345fg' 

कौन सा मुझे आश्चर्य है कि क्यों किसी को भी इस आशय चाहेगा बनाता है। ऐसा लगता है कि यह भ्रमित हो जाएगा। यह कार्यक्रम मुझे लगता है कि आप मूल रूप से किसी के नाम (जैसे टॉम ब्रोकॉ) पर टॉम ब्रो 763 के साथ प्रतिलिपि बना सकते हैं।

strcpy() से अधिकstrncpy()का उपयोग कर के लाभ क्या हैं?

+71

मुझे लगता है कि आप से पूछना करने के लिए होती "क्यों पृथ्वी पर होगा किसी को भी उपयोग' 'बजाय strncpy' की strcpy'?" –

+4

जब मैं सी में पहले सेमेस्टर प्रोग्रामिंग कोर्स के लिए टीए था, तो मैंने अपने छात्रों को आश्वासन दिया कि 'गेटलाइन' जैसी विधियों के किसी भी उपयोग के परिणामस्वरूप गलत परिणाम होंगे जब मैंने सावधानी से तैयार किए गए इनपुट के खिलाफ उन्हें ग्रेड किया था। :) –

+4

मुझे लगता है कि आपने गलत समझा है कि कोड वास्तव में क्या करता है। करीब से देखो। –

उत्तर

76

strncpy उस में लंबाई डाल करने के लिए आप की आवश्यकता द्वारा बफर अतिप्रवाह combats। strcpy पिछला \0 पर निर्भर करता है, जो हमेशा नहीं होता है।

दूसरे, तुम क्यों चुना केवल 7 चरित्र स्ट्रिंग पर 5 अक्षर कॉपी करने के लिए मुझे परे है, लेकिन यह अपेक्षित व्यवहार का निर्माण कर रहा है। यह केवल पहले n वर्णों की प्रतिलिपि बना रहा है, जहां n तीसरा तर्क है।

n कार्यों सभी बफर अतिप्रवाह के खिलाफ बचाव की मुद्रा में कोडिंग के रूप में इस्तेमाल कर रहे हैं। कृपया strcpy जैसे पुराने कार्यों के बदले उनका उपयोग करें।

+38

देखें http://www.lysator.liu.se/c/rat/d11.html: 'strncpy' प्रारंभ में सी लाइब्रेरी में निर्देशिका प्रविष्टियों जैसे संरचनाओं में निश्चित-लंबाई नाम फ़ील्ड से निपटने के लिए पेश किया गया था। इस तरह के खेतों को तारों के समान तरीके से उपयोग नहीं किया जाता है: पिछला भाग अधिकतम लंबाई वाले क्षेत्र के लिए अनावश्यक है, और छोटे नामों के लिए पिछली बाइट्स को सेट करने के लिए कुशल क्षेत्रवार तुलना सुनिश्चित करता है। ** 'strncpy' मूल रूप से "बाध्य स्ट्रैपी" नहीं है, और समिति ने इस तरह के उपयोग के लिए बेहतर तरीके से कार्य करने के बजाय फ़ंक्शन को बदलने के बजाय मौजूदा अभ्यास को पहचानना पसंद किया है। ** –

+29

मुझे यकीन नहीं है कि यह बहुत क्यों हो रहा है अप वोट - strncpy कभी strcpy के लिए एक सुरक्षित विकल्प के रूप में इरादा नहीं किया गया था और वास्तव में कोई सुरक्षित नहीं है क्योंकि यह स्ट्रिंग को शून्य समाप्त नहीं करता है। इसमें अलग-अलग कार्यक्षमता भी है जिसमें यह एनयूएल वर्णों के साथ आपूर्ति की गई लंबाई को पैड करता है। जैसा कि कैफ अपने जवाब में कहता है - यह एक निश्चित आकार सरणी में तारों को ओवरराइट करने के लिए है। – Dipstick

+6

@ क्रिसिस और सीनान: यह अपवॉट हो रहा है क्योंकि सवाल यह था, "आप स्ट्रैपी के बजाय स्ट्रैस्पी का उपयोग क्यों करेंगे?" नहीं, "के लिए strncpy क्या है?" एक अलग अंतर है। यह उत्तर पूर्व को संबोधित करता है, उत्तरार्द्ध नहीं। – Eric

-8

strncpy सच है कि आप strcpy का उपयोग कभी नहीं करना चाहिए, क्योंकि इसकी क्षमता बफर अतिप्रवाह भेद्यता जो आप प्रणाली हमलों

+6

देखें http://www.lysator.liu.se/c/rat/d11.html: strncpy function strncpy प्रारंभ में सी लाइब्रेरी में निर्देशिका प्रविष्टियों जैसे संरचनाओं में निश्चित-लंबाई नाम फ़ील्ड से निपटने के लिए पेश किया गया था। इस तरह के खेतों को तारों के समान तरीके से उपयोग नहीं किया जाता है: पिछला भाग अधिकतम लंबाई वाले क्षेत्र के लिए अनावश्यक है, और छोटे नामों के लिए पिछली बाइट्स को सेट करने के लिए कुशल क्षेत्रवार तुलना सुनिश्चित करता है। strncpy मूल रूप से '' बाध्य strcpy 'नहीं है, और समिति ने इस तरह के उपयोग के लिए बेहतर अनुकूल करने के लिए समारोह को बदलने के बजाय मौजूदा अभ्यास को पहचानना पसंद किया है। –

2

strncpy() समारोह सुरक्षित एक है के सभी तरह की चपेट में आता है की बात के रूप strcpy के सुरक्षित संस्करण है: आपको गंतव्य बफर स्वीकार करने की अधिकतम लंबाई पारित करनी होगी। अन्यथा यह हो सकता है कि स्रोत स्ट्रिंग सही ढंग से 0 को समाप्त नहीं किया गया है, इस स्थिति में strcpy() फ़ंक्शन गंतव्य बफर के बाद स्मृति में मौजूद किसी भी चीज़ को दूषित करने, गंतव्य के लिए और अधिक वर्ण लिख सकता है। यह कई कारनामे

इसके अलावा read() तरह POSIX एपीआई कार्य करता है जो बफर में समाप्त 0 नहीं करता है के लिए

में इस्तेमाल किया बफर-सीमा से अधिक समस्या है, लेकिन रिटर्न बाइट की संख्या पढ़ा, तो आप या तो स्वयं 0 शब्दों में कहें, या होगा इसे strncpy() का उपयोग करके कॉपी करें।

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

0

यह कई अन्य परिदृश्यों में उपयोग किया जा सकता है, जहां आपको अपनी मूल स्ट्रिंग के केवल एक हिस्से की प्रतिलिपि बनाने की आवश्यकता है मंजिल। Strncpy() का उपयोग करके आप स्ट्रिंग() द्वारा विरोध के रूप में मूल स्ट्रिंग के सीमित हिस्से की प्रतिलिपि बना सकते हैं। मैं देखता हूं कि आपके द्वारा डाला गया कोड publib.boulder.ibm.com से आता है।

29

मैं strncpy के पीछे मंशा पता है, ऐसा नहीं वास्तव में एक अच्छा कार्य है। दोनों से बचें। Raymond Chen explains

व्यक्तिगत रूप से, मेरा निष्कर्ष strncpy और उसके सभी दोस्तों से बचने के लिए है यदि आप शून्य-समाप्त तारों से निपट रहे हैं। नाम में "str" ​​के बावजूद, ये फ़ंक्शन नल-टर्मिनेटेड स्ट्रिंग का उत्पादन नहीं करते हैं। वे एक नल-टर्मिनेटेड स्ट्रिंग को कच्चे चरित्र बफर में परिवर्तित करते हैं। उनका उपयोग करना जहां एक नल-टर्मिनेटेड स्ट्रिंग की अपेक्षा की जाती है क्योंकि दूसरा बफर सादा गलत है। यदि स्रोत बहुत लंबा है, तो न केवल आप उचित शून्य समाप्ति प्राप्त करने में विफल रहते हैं, लेकिन यदि स्रोत छोटा है तो आपको अनावश्यक नल पैडिंग मिलती है।

भी Why is strncpy insecure?

136

strncpy() समारोह मन में एक बहुत ही विशेष रूप से समस्या के साथ डिजाइन किया गया था देखें: मूल यूनिक्स निर्देशिका प्रविष्टियों का ढंग से संग्रहीत तार जोड़ तोड़। इन्हें एक निश्चित आकार की सरणी का उपयोग किया जाता था, और एक नल टर्मिनेटर का उपयोग केवल तभी किया जाता था जब फ़ाइल नाम सरणी से छोटा था।

यही कारण है कि strncpy() के दो विषमताएं के पीछे है:

  • यह गंतव्य है, तो यह पूरी तरह से भर जाता है पर एक नुल-टर्मिनेटर डाल नहीं करता है; और
  • यदि आवश्यक हो तो नल के साथ यह हमेशा गंतव्य को भर देता है।

एक "सुरक्षित strcpy()" के लिए, आप तो जैसे strncat() का उपयोग कर बेहतर कर रहे हैं:

if (dest_size > 0) 
{ 
    dest[0] = '\0'; 
    strncat(dest, source, dest_size - 1); 
} 

कि हमेशा परिणाम नुल-समाप्त हो जाएगी, और आवश्यकता से अधिक कॉपी नहीं करेंगे।

+0

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

+0

मुझे इसके कारण का पता नहीं था, और यह एटीएम पर काम करने के लिए बहुत प्रासंगिक है। –

+0

मुझे हमेशा आश्चर्य हुआ कि क्यों strncpy इतना अजीब है। thx –

24

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

  • यदि आप अपनी स्ट्रिंग और बफर की लंबाई जानते हैं, तो strncpy का उपयोग क्यों करें? यह बिजली की गणना में सबसे अच्छा की बर्बादी है (जोड़ने बेकार 0)
  • यदि आप लंबाई पता नहीं है, तो आप चुपचाप अपने तार छोटा है, जो बहुत एक बफर अतिप्रवाह की तुलना में बेहतर नहीं है जोखिम
+0

मुझे लगता है कि यह strncpy के लिए एक अच्छा वर्णन है, इसलिए मैंने इसे वोट दिया है। strncpy यह परेशानियों का अपना सेट है। मुझे लगता है कि यही कारण है कि उदाहरण के लिए ग्लिब के अपने एक्सटेंशन हैं। और हाँ यह दुर्भाग्यपूर्ण है कि प्रोग्रामर के रूप में आपको सभी सरणी के आकार के बारे में पता होना चाहिए। डिकिसन ने स्ट्रिंग के रूप में चार सरणी को समाप्त कर दिया है, जिसने हमें बहुत महंगा लगाया है .... – Friedrich

+0

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

+0

बस विरासत कोड है, जो g_strlcpy (प्रयुक्त) के रखरखाव में पदभार संभाल लिया है, तो गद्दी अक्षमताओं कष्ट नहीं होता है, लेकिन यकीन है कि पर्याप्त, स्थानांतरित बाइट्स की गिनती नहीं रखा गया था, इसलिए कोड चुपचाप परिणाम छोटा था। – user2548100

19

क्या आप देख रहे हैं कि फ़ंक्शन strlcpy() है जो हमेशा 0 के साथ स्ट्रिंग को समाप्त करता है और बफर को प्रारंभ करता है। यह अतिप्रवाह का पता लगाने में भी सक्षम है। केवल समस्या, यह (वास्तव में) पोर्टेबल नहीं है और केवल कुछ सिस्टम (बीएसडी, सोलारिस) पर मौजूद है। इस समारोह के साथ समस्या यह है कि यह कीड़े की एक और कर सकते हैं के रूप में http://en.wikipedia.org/wiki/Strlcpy

मेरे व्यक्तिगत राय पर विचार-विमर्श करके देखा जा सकता है कि यह बेहद strncpy() और strcpy() की तुलना में अधिक उपयोगी है खोलता है। यह बेहतर प्रदर्शन है और snprintf() के लिए एक अच्छा साथी है। प्लेटफ़ॉर्म के लिए जिनके पास यह नहीं है, यह कार्यान्वित करना अपेक्षाकृत आसान है। (एक आवेदन के विकास चरण के लिए मैं इन दो फ़ंक्शन (snprintf() और strlcpy()) को एक फंसे हुए संस्करण के साथ प्रतिस्थापित करता हूं जो बफर ओवरफ्लो या ट्रंकेशन पर क्रूरता से प्रोग्राम को रोकता है। इससे सबसे खराब अपराधी को पकड़ने की अनुमति मिलती है। विशेष रूप से यदि आप कोडेबेस पर काम करते हैं किसी और से।

संपादित करें: strlcpy() आसानी से लागू किया जा सकता है:

size_t strlcpy(char *dst, const char *src, size_t dstsize) 
{ 
    size_t len = strlen(src); 
    if(dstsize) { 
    size_t bl = (len < dstsize-1 ? len : dstsize-1); 
    ((char*)memcpy(dst, src, bl))[bl] = 0; 
    } 
    return len; 
} 
+3

आप लिख सकते हैं कि strlcpy लिनक्स और विंडोज के अलावा अन्य सभी चीज़ों पर उपलब्ध है! हालांकि, बीएसडी लाइसेंस प्राप्त है, इसलिए आप इसे अपने पुस्तकालयों में से एक में छोड़ सकते हैं और वहां से इसका उपयोग कर सकते हैं। –

+0

आप 'dstsize> 0' के लिए एक परीक्षण जोड़ना चाहते हैं और यदि ऐसा नहीं है तो कुछ भी नहीं करें। – chqrlie

+0

हाँ, आप सही हैं। मैं चेक को जोड़ दूंगा क्योंकि इसके बिना 'dstsize' गंतव्य बफर पर' len' की 'memcpy' को ट्रिगर करेगा और इसे बह जाएगा। अच्छे समाधान को बढ़ावा देने के लिए –

2

strncpy, स्रोत के आकार के लिए के साथ '\ 0' गंतव्य भरता eventhough गंतव्य के आकार में छोटा होता है ....

मैनपेज:

हैं src की लंबाई कम से कम एन, strncpy() अशक्त बाइट्स के साथ गंतव्य के शेष के पैड है।

और न केवल शेष ... इसके बाद भी एन वर्ण तक पहुंच गए। और इस प्रकार आपको एक अतिप्रवाह मिलता है ... (मैन पेज कार्यान्वयन देखें)

+2

* strncpy स्रोत के आकार के लिए साइन अप '\ 0' के साथ गंतव्य भरता है, eventhough गंतव्य के आकार में छोटा होता है .... * मुझे डर है कि इस बयान गलत और भ्रामक है कर रहा हूँ: 'strncpy' के साथ गंतव्य भरता है आकार तर्क के लिए '\ 0', यदि स्रोत की लंबाई कम है। आकार तर्क स्रोत का आकार नहीं है, स्रोत से प्रतिलिपि बनाने के लिए वर्णों की अधिकतम संख्या नहीं है, क्योंकि यह 'strncat' में है, यह गंतव्य का आकार है। – chqrlie

+0

@chqrlie: बिल्कुल। अन्य प्रतिलिपि संचालनों पर 'strncpy' का लाभ यह है कि यह गारंटी देता है कि पूरा गंतव्य लिखा जाएगा। चूंकि कंपाइलर्स कुछ अनिश्चित मान वाले संरचनाओं की प्रतिलिपि बनाते समय "रचनात्मक" प्राप्त करने का प्रयास कर सकते हैं, यह सुनिश्चित करना कि संरचनाओं के भीतर कोई चरित्र सरणी पूरी तरह लिखी जाए, "आश्चर्य" को रोकने का सबसे आसान तरीका हो सकता है। – supercat

+0

@supercat: इस विशिष्ट मामले के लिए एक बहुत छोटे से लाभ ... लेकिन गंतव्य 'strncpy' करने के लिए कॉल के बाद समझौता किया जाना चाहिए अशक्त समाप्ति सुनिश्चित करने के लिए:' strncpy (गंतव्य, src, dest_size) [dest_size - 1] = '\ 0 ';' – chqrlie

0

यह हमारी आवश्यकता पर निर्भर करता है। विंडोज उपयोगकर्ताओं के लिए

जब भी हम पूरी स्ट्रिंग की प्रतिलिपि नहीं बनाना चाहते हैं तो हम strncpy का उपयोग करते हैं या हम केवल संख्याओं की प्रतिलिपि बनाना चाहते हैं। लेकिन स्ट्रिपी पूरी स्ट्रिंग को नल चरित्र को समाप्त करने सहित प्रतिलिपि बनाता है।

ये लिंक आपको strcpy और strncpy और जहां हम उपयोग कर सकते हैं, के बारे में और जानने में मदद करेंगे।

about strcpy

about strncpy

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

  • कोई संबंधित समस्या नहीं^_^