2012-02-27 10 views
14
#include<stdio.h> 

int main() 
{ 
    char *name = "Vikram"; 
    printf("%s",name); 
    name[1]='s'; 
    printf("%s",name); 
    return 0; 
} 

टर्मिनल पर मुद्रित कोई आउटपुट नहीं है और केवल सेगमेंटेशन गलती प्राप्त करें। प्राप्तprintf() और सेगमेंटेशन फॉल्ट का निष्पादन

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000400525 in main() at seg2.c:7 
7  name[1]='s'; 
(gdb) 

इस कार्यक्रम का मतलब है SEG 7 लाइन पर गलती (स्पष्ट रूप से मैं लगातार चार सरणी पर नहीं लिख सकते हैं) - लेकिन जब मैं GDB में इसे चलाने, मैं निम्नलिखित मिलता है। फिर लाइन नंबर 6 का printf() क्यों निष्पादित नहीं किया गया है?

+0

मुझे पूरा यकीन नहीं है। यह मेरे मैक चल रहे ओएसएक्स शेर (एलएलवीबी के साथ डीबग किए गए एलएलवीएम के साथ अनुपालन) पर अपेक्षित काम करता है। –

उत्तर

30

यह stdout की धारा बफरिंग के कारण है। जब तक आप fflush(stdout) नहीं करते हैं या आप एक नई लाइन "\n" प्रिंट करते हैं तो आउटपुट buffered किया जा सकता है।

इस मामले में, यह बफर फ़्लश और मुद्रित होने से पहले segfaulting है।

आप इस बजाय कोशिश कर सकते हैं:

printf("%s",name); 
fflush(stdout);  // Flush the stream. 
name[1]='s';   // Segfault here (undefined behavior) 

या:

printf("%s\n",name); // Flush the stream with '\n' 
name[1]='s';   // Segfault here (undefined behavior) 
+6

ध्यान दें कि 'fflush' वास्तव में ऐसा करने का सही तरीका है - फ्लश को ट्रिगर करने की गारंटी नहीं है (और मुझे पहले उस व्यवहार से काटा गया है)। –

4

कारण आप हो रही है एक विभाजन गलती है कि सी स्ट्रिंग शाब्दिक केवल सी मानक के अनुसार पाठ किया जाता है, और आप शाब्दिक सरणी "विक्रम" के दूसरे तत्व पर 'लिखने' का प्रयास कर रहे हैं।

कारण आपको कोई आउटपुट नहीं मिल रहा है क्योंकि आपका प्रोग्राम अपने बफर को फ्लश करने का मौका देने से पहले अपने आउटपुट और क्रैश को बफर कर रहा है। Stdio लाइब्रेरी का उद्देश्य, printf (3) जैसे दोस्ताना स्वरूपण फ़ंक्शंस प्रदान करने के अलावा, इन-मेमोरी बफर में डेटा बफर करके आई/ओ संचालन के ओवरहेड को कम करना और आवश्यक होने पर केवल आउटपुट फ्लश करना, और केवल कभी-कभी इनपुट करना लगातार की बजाय। वास्तविक इनपुट और आउटपुट, सामान्य स्थिति में, उस समय होते हैं जब आप stdio फ़ंक्शन को कॉल करते हैं, लेकिन केवल जब आउटपुट बफर भरा होता है (या इनपुट बफर खाली होता है)।

यदि कोई फ़ाइल ऑब्जेक्ट सेट किया गया है तो यह थोड़ा अलग होता है, इसलिए यह लगातार (जैसे stderr) flushes, लेकिन सामान्य रूप से, यह बात है।

यदि आप डिबगिंग कर रहे हैं, तो यह सुनिश्चित करने के लिए कि आपके डीबग प्रिंटआउट को दुर्घटनाग्रस्त होने से पहले फ़्लश किया जाए, यह सबसे अच्छा है।

9

सबसे पहले आपको अपने प्रिंटफेस को "\ n" (या कम से कम अंतिम) के साथ समाप्त करना चाहिए। लेकिन यह segfault से संबंधित नहीं है।

जब संकलक आपके कोड को संकलित करता है, तो यह बाइनरी को कई खंडों में विभाजित करता है। कुछ केवल पढ़े जाते हैं, जबकि अन्य लिखने योग्य होते हैं। केवल पढ़ने वाले अनुभाग में लिखने से segfault हो सकता है। स्ट्रिंग अक्षर आमतौर पर केवल पढ़ने के लिए खंड में रखा जाता है (जीसीसी इसे ".rodata" में रखना चाहिए)। सूचक नाम उस ro खंड को इंगित करता है। इसलिए आपको

const char *name = "Vikram"; 

मेरी प्रतिक्रिया में मैंने कुछ "मई" "का उपयोग किया होगा"। व्यवहार आपके ओएस, कंपाइलर और संकलन सेटिंग्स पर निर्भर करता है (लिंकर स्क्रिप्ट अनुभागों को परिभाषित करता है)।

जीसीसी के कमांड लाइन के लिए

-Wa,-ahlms=myfile.lst 

जोड़ना एक फ़ाइल उत्पन्न कोडांतरक कोड के साथ myfile.lst कहा जाता है। आप देख सकते हैं शीर्ष पर

.section .rodata 
.LC0: 
    .string "Vikram" 

जो दिखाता है कि स्ट्रिंग विक्रम में है।

एक ही कोड का उपयोग कर (वैश्विक दायरे में होना चाहिए, और जीसीसी, ढेर पर संग्रहीत कर सकते हैं यह एक सरणी और नहीं एक सूचक है नोटिस)

char name[] = "Vikram"; 

पैदा करता

.data 
    .type name, @object 
    .size name, 7 
name: 
    .string "Vikram" 

वाक्यविन्यास थोड़ा अलग है लेकिन देखें कि यह अब .डेटा अनुभाग में कैसा है, जो पढ़ना है। इस उदाहरण से काम करता है।

+1

यदि आप देखते हैं, तो ओपी नहीं पूछ रहा है कि segfault क्यों होता है, लेकिन स्ट्रिंग को पहले स्थान पर क्यों मुद्रित नहीं किया गया था। –

+1

हालांकि यह प्रश्न का बिल्कुल सही जवाब नहीं हो सकता है, टिप और व्याख्या .rodata और .data पर उपयोगी है। – vts

0

डिफ़ॉल्ट रूप से stdout टर्मिनल से जुड़ा हुआ है, स्ट्रीम लाइन-बफर है। व्यावहारिक रूप से, आपके उदाहरण में '\n' (या एक स्पष्ट स्ट्रीम फ्लश) की अनुपस्थिति है, इसलिए आपको वर्णों को मुद्रित नहीं किया जाता है।

लेकिन सिद्धांत रूप में अपरिभाषित व्यवहार घिरा नहीं है (मानक से "व्यवहार [...] जिसके लिए इस अंतर्राष्ट्रीय मानक नहीं आवश्यकताओं लगाता है") और पहले भी अपरिभाषित व्यवहार से पहले उदाहरण के लिए, तब होता है segfault हो सकता है पहले printf कॉल करें!

+0

तो ... आप कह रहे हैं कि व्यवहार इतना अनिर्धारित है कि यह समय * पीछे * कार्य कर सकता है? –