2013-10-12 69 views
2

我有一個基本程序,通過readline函數從用戶接收用戶命令「command varname = variable」。然後它解析字符串以將每個部分存儲到字符串變量中。我遇到的問題是我得到一個錯誤:分段默認(核心轉儲)這應該是來自非法內存訪問,但我已經通過我的程序一行一行的樣本輸入:「集射線」,我不知道這是發生在哪裏。我的預期結果是命令應該包含set,Varname應該包含ray,並且Value應該爲NULL這裏是代碼以及示例輸入和輸出,顯示錯誤。我也看到一個錯誤:總線(核心轉儲)顯示一次。任何想法,這個錯誤來自哪裏?C程序段默認(核心轉儲)

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <readline/readline.h> 
#include <readline/history.h> 

/* Simple example of using gnu readline to get lines of input from a user. 
    Needs to be linked with -lreadline -lcurses 
    add_history tells the readline library to add the line to it's 
    internal histiry, so that using up-arrow (or ^p) will allows the user 
    to see/edit previous lines. 
*/ 


int main(int argc, char **argv) { 

    char * s; 
    char * Command; 
    char * Varname; 
    char * Value; 

    while (s=readline("Enter Name: ")) { 
    add_history(s); /* adds the line to the readline history buffer */ 

    printf("Hello %s\n",s);/*output message to the user*/ 

    int part = 1; 
    int i; 

    for (i = 0; i < strlen(s); i++) 
     { 

     while((isspace(s[i]) || s[i] == '=') && (i < strlen(s))) 
      { 
      i++;//parse the string for the next portion of the command    
      } 

     if(i >= strlen(s)) 
      { 
      printf("Error: Command not properly formatted!\n"); 
      break;//terminate the for loop 
      }   

     if(part == 1)//grab the command 
      { 
      int size1 = 0;//size of the command 
      int j = i;//index of the first non-space character in this portion of the string 

      while(!isspace(s[j]))//determine the size of the command, j will point to space when the loop exits 
       { 
       size1++; 
       j++;        
       } 

      Command = (char*) malloc (size1+1);//allocate space to hold the characters of the command along with the terminating '\0' character 

      int d = 0;//destination index 
      while(i<j) 
       { 
       Command[d] = s[i];//copy the characters of the command portion of s over to the command array 
       d++; 
       i++; 
       } 

      Command[d] = '\0';//terminating null character 
      part++;//increment the part of the command 

      } 
     else if(part == 2)//grab the varname 
      { 
      int size2 = 0;//initialize the size of the character array which will hold the variable name 
      int k = i; 
      while(!isspace(s[k]))//determine the size of the varname, k will be at the next space when the loop exits 
       { 
       size2++; 
       k++;        
       } 

      Varname = (char*) malloc (size2+1);//allocate space to hold the characters of the Varname along with the terminating '\0' character 

      int e = 0; 
      while(i<k) 
       { 
       Varname[e] = s[i];//copy the characters of the Varname portion of s over to the Varname string 
       e++; 
       i++; 
       } 
      Varname[e] = '\0'; 
      part++;//increment part 
      } 
     else if(part == 3)//grab the value if one is given 
      { 
      int size3 = 0;//initialize the size of the character array which will hold the value of the environment variable 
      int l = i; 
      while(!isspace(s[l]) && s[l] != '\0')//determine the size of the varname and check if we've reached the end of the string 
       { 
       size3++; 
       l++;        
       } 

      Value = (char*) malloc (size3+1);//allocate space to hold the characters of the Value along with the terminating '\0' character 
      int f = 0; 
      while(i<l) 
       { 
       Value[f] = s[i];//copy the characters of the command portion of s over to the command array 
       f++; 
       i++; 
       } 
      Value[f] = '\0'; 
      } 
     } 
    /*print out the sections of the full command*/ 
    if(Command != NULL) 
     { 
     printf("Hey %s\n",Command); 
     } 
    if(Varname != NULL) 
     { 
     printf("Hey %s\n",Varname); 
     } 
    if(Value != NULL) 
     { 
     printf("Hey %s\n",Value); 
     } 

    /* clean up! */ 
    free(s); 
    free(Command); 
    free(Varname); 
    free(Value); 
    } 
    return(0); 
} 

樣品輸入/輸出:

Enter Name: set ray = 21 
Hello set ray = 21 
Hey set 
Hey ray 
Hey 21 
Enter Name: print ray 
Hello print ray 
Hey print 
Hey ray 
Hey 
Enter Name: delete varname 
Hello delete varname 
Hey delete 
Hey varname 
Hey delete 
Enter Name: print raymond 
Hello print raymond 
Hey print 
Hey raymond 
Hey 
Enter Name: delete variable 
Hello delete variable 
Hey delete 
Hey variable 
Segmentation fault (core dumped) 
+0

學習使用調試器。錯誤「核心轉儲」的第二部分表示運行時系統已生成「核心」文件。如果你用'-g'選項編譯你的程序,'gdb your-progname core'應該告訴你程序出錯的地方。 –

+1

稍有相關:這是['strtok()'](http://en.cppreference.com/w/c/string/byte/strtok)的原因,如果你有可能90%的代碼會消失用它。 – WhozCraig

回答

1

你不初始化他們

char * Command; 
char * Varname; 
char * Value; 

根據用戶輸入的內容聲明瞭三個三分球,這可能不是所有被初始化爲指向在您的for循環內動態分配內存。如果他們不是所有的初始化,試圖free後來他們將有可能崩潰

free(Command); 
free(Varname); 
free(Value); 

的最簡單的解決將是初始化所有的變量NULL在處理每一行的開始

while (s=readline("Enter Name: ")) { 
    Command = NULL; 
    Varname = NULL; 
    Value = NULL; 

它然後可以安全地撥打free,即使它們仍然設置爲NULL

+0

他應該在循環開始時將它們清零。否則,他們仍然會保留上一次迭代的值,然後他將兩次釋放它們。 – Barmar

+0

謝謝,這個問題中的縮進讓我意識到了。我現在糾正了我的答案。 – simonc

+0

謝謝,這似乎工作。如果沒有其他指定,我假設指針默認爲NULL。 –