2013-10-12 3 views
2

사용자 명령에서 "command varname = variable" readline 기능을 사용하는 기본 프로그램이 있습니다. 그런 다음 문자열을 파싱하여 각 부분을 문자열 변수에 저장합니다. 내가 겪고있는 문제는 다음과 같습니다. 세그먼트 화 기본값 (코어가 덤프 됨) 이는 불법적 인 메모리 액세스로 인한 것입니다. 그러나 프로그램에서 한 줄씩 샘플 프로그램을 살펴 보았습니다. 입력 : "set ray" 그리고 이것이 어디에서 발생하는지 알 수 없습니다. 내 기대 결과는 명령은 집합을 포함해야하며 Varname은 광선을 포함해야하며 값은 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; 

그것을 그래도 NULL으로 설정되어 있어도 free에 전화해도 안전합니다.

+0

그는 루프의 시작 부분에서이를 무시해야합니다. 그렇지 않으면 이전 반복의 값을 보유하게되며 두 번 해제됩니다. – Barmar

+0

감사합니다, 질문에 들여 쓰기가 나를 잡았습니다. 나는 지금 내 대답을 바로 잡았다. – simonc

+0

감사합니다. 이것은 효과가있는 것 같습니다. 아무 것도 지정하지 않으면 기본적으로 포인터가 NULL로 간주됩니다. –