2013-03-08 2 views
0

명령 줄 셸에 대한 내역 기능을 구현하고 있습니다. 가장 최근의 명령 10 개를 보유 할 원형 배열을 구현했습니다. 각 명령은 또한 총 명령이 무엇인지를 지정하는 정수로 표시됩니다. 예를 들어 총 명령 30 개를 입력하면 원형 배열에있는 10 개의 명령에 번호가 매겨집니다 (30, 29, 28, 27, ..., 21).세그먼트 화 오류 - strcpy() - C

사용자가 명령 "r"을 입력 한 다음 10 개의 명령어 중 하나를 레이블링하는 번호를 입력하면 해당 명령어가 실행되어야합니다. 두 단어 명령이 올바르게 수용되도록 할 때 계속 seg 오류가 발생합니다. 아무도 문제가 무엇인지 지적 할 수 있습니까?

int main(void) 
{ 
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */ 
    int background;    /* equals 1 if a command is followed by '&' */ 
    char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */ 

    int position, count, rnum = 0; 
    char historyArray[10][MAX_LINE]; 
    char *holder[MAX_LINE]={0}; 

    while (1){   /* Program terminates normally inside setup */ 
     background = 0; 
     printf("COMMAND->"); 
     fflush(0); 

     setup(inputBuffer, args, &background);  /* get next command */ 

     position = (count % MOD_VAL); 
     strcpy(historyArray[position],args[0]); 

     if(!strcmp("rr",args[0])) 
     { 
      strcpy(historyArray[position],historyArray[((position-1)+MOD_VAL)%MOD_VAL]); 
      printf("%i",count); 
      printf("%c",'.'); 
      printf("%c",' '); 
      printf("%s",historyArray[position]); 
      printf("%c",'\n'); 
      strcpy(args[0],historyArray[position]); 
     } 

     else if(!strcmp("r",args[0])) //SEG FAULT OCCURING IN THIS ELSE-IF BLOCK! 
     { 
      //args[1] will hold given number 
      printf("%c",'\n'); 
      printf("%s",args[0]); 
      printf("%s",args[1]); 
      printf("%s",args[2]); 
      printf("%c",'\n'); //PRINT STATEMENTS FOR DEBUGGING 

      strncpy(holder[0], args[2], MAX_LINE - 1); //SEG FAULT 

      rnum = atoi(args[1]); 
      strcpy(historyArray[position],historyArray[((position-(count-rnum))+MOD_VAL)%MOD_VAL]); 
      strcpy(args[0],historyArray[position]); //CHANGES VALUES OF args[1], args[2] 

      if(holder[0] != NULL) 
      { 
       strncpy(args[1],holder[0],MAX_LINE-1); 
       args[2] = NULL; 
      } 
      else 
      { 
       args[1] = NULL; 
      } 

      printf("%c",'\n'); 
      printf("%s",args[0]); 
      printf("%s",args[1]); 
      printf("%s",args[2]); 
      printf("%c",'\n'); 
     } 

     else if(!(strcmp("h",args[0]))||!(strcmp("history",args[0]))) 
     { 
      int counter = 0; 
      while(counter < 10) 
      { 
       printf("%i",(count - counter)); 
       printf("%c",'.'); 
       printf("%c",' '); 
       printf("%s", historyArray[((position - counter + MOD_VAL)%MOD_VAL)]); 
       printf("%c",' '); 
       printf("%c",'\n'); 
       counter ++; 

       if(counter > count) 
        break; 
      } 
     } 
     count++; 

     pid_t pid1; //Initialize pid_t variable to hold process identifier 
     pid1 = fork(); //Fork process and assign process identifier to "pid1" 

     if (pid1 == 0) //Child process 
     { 
      //Child process executes the command specified by the user and 
      //then quits. 
      execvp(args[0], args); 
      exit(0); 
     } 
     else //Parent process 
     { 
      if (background != 1)//Check for inclusion of '&' in command 
      { 
       wait(NULL); //Wait for child process to finish executing 
      } 
     } 

     /* the steps are: 
     (1) fork a child process using fork() 
     (2) the child process will invoke execvp() 
     (3) if background == 0, the parent will wait, 
     otherwise returns to the setup() function. */ 
    } 
} 

도움을 주시면 감사하겠습니다. 내가 당신이라면, 디버거에서 코어 파일을로드 args[0]의 값이 전달 될 때 무엇을 볼 것입니다

else if(!strcmp("r",args[0])) 

- 매트

+0

매트, 들여 쓰기를 수정할 수 있습니까? 또한, 코드는'else if'로 시작하는데별로 의미가 없습니다. – JohnnyHK

+0

구현은 모든 단일 단어 명령 (ls)에 대해 올바르게 작동합니다. mkdir dirname과 같은 입력 명령에 대해 작동하는지 확인하려고 시도합니다. 사용자 입력 : r 1 dirname; 여기서 r = args [0], 1 = args [1], dirname = args [2]. else-if의 경우 args [1]에 dirname이 필요합니다! –

+0

죄송합니다. 코드의 길이가 다소 길어서 게시 할 수 있을지 불확실했습니다. –

답변

3

여기서 args는 문자 포인터의 배열입니다. array 또는 character pointer to which memory allocated by malloc

을해야한다고하지만 당신의 strcpy(historyArray[position],args[0]);은 허용되지 않습니다 character pointer 하나 개 인수를 취하는 -

그러나 strcpy는 두 개의 인수가 필요합니다.

이므로 args[]args[][] 또는 args[0] = malloc(some_no)으로 변경하면 segfault이 제거됩니다.

+0

'args []'와 같은 선언이 없습니다. 그리고 args [] []는 문제의 포인터에 메모리를 할당하지 않으며 컴파일도하지 않습니다. – alk

0

당신은 충돌이 라인에서 발생주의 strcmp().

유형 불일치에 대한 컴파일러 경고가 charchar* 사이 일 것으로 예상됩니다. args를 char*으로 선언하십시오. 즉, args[0]char이고 char*이 아닙니다. 단일 문자를 비교하기 위해, 단지 strcmp() 대신 문자를 사용 : 함정에

else if ('r' != args[0]) 

일부 메모를 C의 문자열 처리와 함께 :

  • strcmp() 배열 경계 경우에 대한 안전하지 않습니다 해당 인수가 올바르게 NUL 종료되지 않았습니다.
    • strncmp()을 사용하여 비교 된 문자 수에 대한 제한을 제공하십시오.
    • 배열 경계에 대한 strncpy() 경비원, 그것은을 보장하지 않지만
  • strcpy() 배열의 경계를 존중하지 않는 대상 문자열을 NUL - 종료; 대상 배열이 복사 할 문자열을받을만큼 충분히 큰지 확인하는 것은 사용자의 책임입니다.
+0

세그먼트 화 오류는 해당 else-if 블록 내에서 발생합니다. 실제 줄 오류는 다음 줄에서 발생합니다. ** strncpy (holder [0], args [2], MAX_LINE - 1); ** ** 팁 주셔서 감사합니다! –

+0

"... 당신은 args를 char *로 선언합니다. 즉, args [0]은 char *가 아니라 char * ..."적어도 OP의 현재 버전에서 이것은 잘못된 것입니다. 'args'는'(char *) []'로 선언되어'args [0]'은'char * '가되어'strcmp()'에 전달할 수 있습니다. 실제로'('r'! = args [0])'은 컴파일러에 의해 "타입 불일치"경고를 유발할 수 있습니다. – alk

+0

오른쪽 - 내 실수. 변수 이름 다음에 여분의 배열 차원을 놓쳤습니다. 자바의 구문이 변수 대신 배열에 대괄호를 사용하는 것을 좋아합니다. :) – dsh

-1

char 포인터가 argsholder에 저장되어있어 할당 된 메모리가 누락되었습니다.

따라서 str*() 패밀리를 통해 0으로 종료되는 문자 배열 ("문자열")에 대한 포인터를 참조하면 str*() 함수가 유효한 메모리를 가리 키지 않도록하기 때문에 정의되지 않은 코드가 생깁니다.

+0

downvoter는 무엇이 잘못되었는지 설명하고 싶습니까? – alk