2012-05-19 11 views
8

निम्नलिखित कोड सेगमेंटेशन गलती के साथ क्यों लौटाता है? जब मैं लाइन 7 पर टिप्पणी करता हूं, तो सीजी गलती गायब हो जाती है।सेगमेंटेशन फॉल्ट - सी

int main(void){ 
     char *s; 
     int ln; 
     puts("Enter String"); 
     // scanf("%s", s); 
     gets(s); 
     ln = strlen(s); // remove this line to end seg fault 
     char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome 
     dyn_s = s; 
     dyn_s[strlen(s)] = '\0'; 
     puts(dyn_s); 
     return 0; 
    } 

चीयर्स!

+0

@Lundin विभाजन गलती त्रुटि के लिए नेतृत्व नहीं करेंगे, कृपया का कहना है कि इस का डुप्लिकेट है ? यदि आप https://stackoverflow.com/questions/37549594/why-do-i-get-a-mysterious-crash-or-segmentation-fault-when-i-copy-scan-data-to का जिक्र कर रहे हैं , मैं कहूंगा कि मेरा प्रश्न 4 साल पुराना है – ceod

उत्तर

12

s एक प्रारंभिक सूचक है; आप स्मृति में एक यादृच्छिक स्थान पर लिख रहे हैं। यह अपरिभाषित व्यवहार का आह्वान करेगा।

आपको s के लिए कुछ मेमोरी आवंटित करने की आवश्यकता है। इसके अलावा, never use gets; आपके द्वारा आवंटित स्मृति को बहने से रोकने का कोई तरीका नहीं है। इसके बजाय fgets का उपयोग करें।

+0

धन्यवाद बहुत ओली! मुझे कीट होने के लिए क्षमा करें, लेकिन, क्या मैं समझता हूं कि मैंने जिस पंक्ति का उल्लेख किया है, वह अपरिभाषित व्यवहार को सीजी गलती के कारण बनता है। क्या आप मुझे कुछ और कारणों को देखने में मदद कर सकते हैं? – ceod

+0

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

+0

बहुत बहुत धन्यवाद ओली! – ceod

2

भयंकर बुरा:

int main(void){ 
     char *s; 
     int ln; 
     puts("Enter String"); 
     // scanf("%s", s); 
     gets(s); 
     ln = strlen(s); // remove this line to end seg fault 
     char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome 
     dyn_s = s; 
     dyn_s[strlen(s)] = '\0'; 
     puts(dyn_s); 
     return 0; 
    } 

बेहतर:

#include <stdio.h> 
#define BUF_SIZE 80 

int 
main(int argc, char *argv[]) 
{ 
     char s[BUF_SIZE]; 
     int ln; 
     puts("Enter String"); 
     // scanf("%s", s); 
     gets(s); 
     ln = strlen(s); // remove this line to end seg fault 
     char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome 
     dyn_s = s; 
     dyn_s[strlen(s)] = '\0'; 
     puts(dyn_s); 
     return 0; 
    } 

बेस्ट:

#include <stdio.h> 
#define BUF_SIZE 80 

int 
main(int argc, char *argv[]) 
{ 
     char s[BUF_SIZE]; 
     int ln; 
     puts("Enter String"); 
     fgets(s, BUF_SIZE, stdin); // Use fgets (our "cin"): NEVER "gets()" 

     int ln = strlen(s); 
     char *dyn_s = (char*) malloc (ln+1); 
     strcpy (dyn_s, s); 
     puts(dyn_s); 
     return 0; 
    } 
+0

बेहतर अभी भी: 'char * dyn_s = malloc (ln + 1);'। और ध्यान दें कि 'fgets() 'बफर में समाप्ति' '\ n'' छोड़ देता है; '()' इसे छोड़ देता है (लेकिन 'हो जाता है() 'अभी भी विनाशकारी रूप से खराब है)। –

+0

कूल! धन्यवाद। आपके द्वारा लिंक किए गए किसी भी महान संसाधन, आमतौर पर उपयोग किए गए आईओ कार्यों के व्यवहार को wrt? – ceod

+0

और 'cast'' malloc() 'परिणाम हटाने के अलावा, जांचें कि क्या आपको' न्यूल 'मान प्राप्त नहीं हुआ है या नहीं। 'char * dyn_s = malloc (ln + 1); अगर (! dyn_s) {printf ("कोई mem! \ n"); बाहर निकलें (EXIT_FAILURE);} 'या आप एक और सेगमेंटेशन गलती प्राप्त कर सकते हैं। –

1

आपका scanf("%s", s); बाहर टिप्पणी की है। इसका मतलब है कि एस अनियमित है, इसलिए जब यह लाइन ln = strlen(s); निष्पादित होती है, तो आपको सीजी गलती मिलती है।

यह हमेशा पॉइंटर को न्यूल में प्रारंभ करने में मदद करता है, और उसके बाद पॉइंटर का उपयोग करने से पहले शून्य के लिए परीक्षण करता है।

+0

धन्यवाद! नल पॉइंटर प्रारंभिकरण और अधिक बार परीक्षण करेंगे। मुझे नहीं लगता कि मुझे स्कैनफ हिस्सा मिल गया है। स्कैनफ भी असफल नहीं होना चाहिए? आखिरकार, सूचक कुछ भी शुरू नहीं हुआ है और स्ट्रिंग की प्रारंभिक स्थिति के रूप में कुछ मनमानी और अवैध स्थान को इंगित कर सकता है, इसलिए एक सीजी गलती? मैंने इसे टिप्पणी की, क्योंकि इसमें सीजी दोष भी शामिल थे। या मैं कुछ समझने में असफल रहा हूँ? – ceod

+0

यह उत्तर ** गलत ** है। यदि आप उस पॉइंटर को न्यूल में प्रारंभ करते हैं, तो इसके परिणामस्वरूप यूबी - न्यूल को कभी भी संदर्भित नहीं किया जाएगा, स्कैनफ द्वारा भी नहीं ... –

+0

मैं अपने पॉइंटर्स का परीक्षण करता हूं कि वे शून्य पर सेट हैं या नहीं। यदि उपयोग करने से पहले शून्य करने के लिए प्रारंभ किया गया है, तो एक उचित मौका है कि सूचक पहले से ही वैध स्मृति को असाइन नहीं किया गया है। – octopusgrabbus

1

और भी बेहतर

#include <stdio.h> 
int 
main(void) 
{ 
    char *line = NULL; 
    size_t count; 
    char *dup_line; 

    getline(&line,&count, stdin); 
    dup_line=strdup(line); 

    puts(dup_line); 

    free(dup_line); 
    free(line); 

    return 0; 
} 
+0

हाय! मैंने कभी भी getline() और strdup() फ़ंक्शंस का उपयोग नहीं किया है। मुझे नहीं लगता कि मैंने उन्हें पहले भी देखा है। उन्हें मुझे पेश करने के लिए धन्यवाद;)। उम्म दुर्भाग्य से आपका कोड एक सीजी गलती में चलाता है! – ceod

+0

अजीब। निहित घोषणा के बारे में चेतावनी, मेरे लिए सही काम। जीएनयू/लिनक्स सिस्टम, जीसीसी 4.6.3। – KAction

+0

'लाइन' को न्यूल के साथ प्रारंभ किया जाना चाहिए। हाँ, सी क्रूर हो सकता है। – KAction

1
char *s does not have some memory allocated . You need to allocate it manually in your case . You can do it as follows 
s = (char *)malloc(100) ; 

इस के रूप में आप एक अज्ञात स्थान के लिए अब और बात कर नहीं लिया जाएगा

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