2010-09-03 13 views
5
#include<stdio.h> 

void main() 
{ 
    char *p="nyks"; 

    p[2]='n'; 

    printf("%s",p); 
} 

यह सेगमेंटेशन FAULT के साथ दुर्घटनाग्रस्त हो जाता है। क्या कोई समझा सकता है क्यों?इस सी प्रोग्राम segfault में एक स्ट्रिंग अक्षर के लिए लेखन क्यों लिखता है?

+0

क्या मंच? मेरे लिये कार्य करता है... –

उत्तर

7

मानक निर्धारित करता है कि शाब्दिक तारों को const परिभाषित किया गया है। आप इसे बदल नहीं सकते

कंपाइलर एक रीडोनली मेमोरी सेक्शन में शाब्दिक स्थान रखता है। आप असेंबली आउटपुट कर सकते हैं और इसका निरीक्षण कर सकते हैं। यदि आप जीसीसी का उपयोग कर रहे हैं तो यह ध्वज के माध्यम से किया जाता है। यह एक .rodata खंड में स्ट्रिंग रखेगा।

#include<stdio.h> 
const char privatestring[5] = {"nyks"}; 

void main() 
{ 
    char *p = const_cast<char*>(privatestring); 
    p[2]='n';   

    printf("%s",p);   
}   

संकलक करने के लिए अनुमति दी है:

+0

के संदर्भ के लिए +1 और यदि मैं चार arr [10] = "nyks" लिखता हूं; एआर [2] = 'पी'; क्या यह फिर से सीजी गलती दिखाएगा? – Kraken

+1

@ हॉपफुल, नहीं। यह ठीक है, क्योंकि आप ढेर पर एक (संशोधित) सरणी आवंटित कर रहे हैं। जैसा कि मैंने उपरोक्त उल्लेख किया है, आप आकार छोड़ सकते हैं ताकि सी इसकी गणना कर सके। –

+1

नहीं, सी में, स्ट्रिंग अक्षर में 'const' प्रकार नहीं है। हालांकि, यह उन्हें लिखने के लिए अपरिभाषित व्यवहार है। –

15

यह एक स्ट्रिंग अक्षर को ओवरराइट करने का प्रयास करने के लिए अपरिभाषित व्यवहार है। C99 §6.4.5/6:

कार्यक्रम एक सरणी संशोधित करने के लिए इस तरह के प्रयास करता है, व्यवहार unde फाई नेड है।

यह परिशिष्ट जे 2 (अपरिभाषित व्यवहार) में बहाल किया गया है।

तो आप के बजाय कार्य करें:

char p[] = "nyks"; 

आप आवंटित और एक स्वत: (ढेर) चरित्र सरणी को प्रारंभ कर सकते हैं। उस स्थिति में, तत्वों को संशोधित करना बिल्कुल ठीक है।

+0

+ इसे गैर-निरंतर स्ट्रिंग शाब्दिक घोषणाओं की अनुमति नहीं है। जीसीसी एक बड़ी लाल चेतावनी जारी करेगा। –

+0

spec – linuxuser27

0

स्ट्रिंग शाब्दिक संशोधन करने योग्य नहीं हैं ... char *p="nyks"; लिखने की क्षमता वास्तव में सी

+0

यह एक प्रकार का सिस्टम छेद कैसा है? – alternative

+0

ऐतिहासिक कारणों से, इस मामले में संकलक को चुपचाप 'कॉन्स्ट' को दूर करने की अनुमति थी। बेशक, उस समय 'कॉन्स्ट' का आविष्कार किया गया था और उन्होंने देखा कि एक स्ट्रिंग निरंतर प्रभावी रूप से 'कॉन्स्ट चार *' होना चाहिए, यह संभवतः 'char *' के असाइनमेंट को रोकने के लिए बड़े ब्रेकिंग परिवर्तन के रूप में माना जाता था। – RBerteig

+0

@mathepic यह कम से कम C++ बिंदु दृश्य से है। सी ++ में, एक वर्ण शाब्दिक प्रकार का प्रकार चार [एन] है। एक स्ट्रिंग शाब्दिक रूप से गैर-कॉन्स चार * (कॉस्ट योग्यता को कास्ट के बिना हटाया जा सकता है) में परिवर्तित किया जा सकता है। यह सी ++ में एक प्रकार का सिस्टम छेद है, लेकिन यह व्यवहार सी से विरासत में मिला था। यह सी ++ में एक बहिष्कृत विशेषता है, और इसे पूरी तरह से C++ 0x में हटा दिया जाएगा। इस प्रश्न के मामले पर सी मानक को क्या कहना है: "यदि प्रोग्राम इस तरह के सरणी को संशोधित करने का प्रयास करता है, तो व्यवहार अपरिभाषित है।" जहां 'ऐसी एरे' एक वर्ण सरणी है जिसमें स्ट्रिंग अक्षर होता है। – usta

1

में एक प्रकार प्रणाली छेद है कि करने के लिए (अनिवार्य) तब्दील है privatestring कहीं कहीं रखें जहां आपने केवल पहुंच पढ़ी है। यह पिछड़ा संगतता के लिए const_cast है जो पहले लिखा गया प्रोग्राम था, जो कि एक कॉन्स कीवर्ड था।

3

अन्य उत्तरों मानकों के परिप्रेक्ष्य से दृश्य कहते हैं, लेकिन यहां है यह क्रैश हो जाता है।

कंपाइलर्स आम तौर पर प्रोग्राम अक्षर - विशेष रूप से तार - केवल पढ़ने योग्य स्मृति में डालते हैं। स्मृति को ओएस द्वारा केवल पढ़ने के लिए चिह्नित किया जाता है, इसलिए इसे लिखने का कोई भी प्रयास फंस जाएगा और आपके प्लेटफॉर्म पर, सेगमेंटेशन गलती यही इंगित करती है; कुछ स्मृति पर ऑपरेशन करने का प्रयास जिसकी अनुमति नहीं है। खराब स्मृति उपयोग से जुड़े अन्य प्रकार की दुर्घटना एक बस त्रुटि है, जो आम तौर पर एक गैर-गठबंधन स्मृति पहुंच या उस पृष्ठ पर लिखने का संकेत देती है जो मैप नहीं है। सी कोड के लिए, अंतर लगभग पूरी तरह अकादमिक है (कुछ अन्य भाषा कार्यान्वयन इन दोषों का उपयोग स्मृति को प्रबंधित करने में उनकी सहायता के लिए करते हैं)।

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

+0

और (C89) मानक निर्दिष्ट नहीं करता है कि जब आप एक शाब्दिक रूप से लिखते हैं तो क्या होता है क्योंकि वे एक सटीक तरीका निर्दिष्ट नहीं करना चाहते थे जिसमें दुर्घटना होती है, और क्योंकि वे कंप्यूटर्स को लिखने योग्य स्ट्रिंग का समर्थन करने की अनुमति देना चाहते हैं वे चाहते थे (उदाहरण के लिए, एक स्विच के माध्यम से; जीसीसी के पास उस तरह की चीज करने के लिए '-फ्राइटेबल-स्ट्रिंग्स' है, हालांकि अगर आप मुझसे पूछें तो वास्तव में एक बुरी तरह टूटा हुआ कार्यक्रम का संकेत है)। –

1

मान एक स्ट्रिंग अक्षर है जिसे संशोधित नहीं किया जा सकता है क्योंकि अक्षर को केवल स्मृति में संग्रहीत किया जाता है, इसके बजाय p [] कोशिश करें। सामान्यतः पॉइंटर्स के गलत उपयोग के कारण विभाजन की त्रुटियां होती हैं।

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