2009-09-02 4 views
0

문자열을 chdir()에 전달하려고합니다. 하지만 난 항상 몇 가지 후행 물건 chdir() 실패하게 보인다.C에서 문자열 파싱

#define IN_LEN 128 

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

    int counter; 
    char command[IN_LEN]; 
    char** tokens = (char**) malloc(sizeof(char)*IN_LEN); 
    size_t path_len; char path[IN_LEN]; 

     ... 

    fgets(command, IN_LEN, stdin) 
    counter = 0; 
    tmp = strtok(command, delim); 
    while(tmp != NULL) { 
     *(tokens+counter) = tmp; 
     tmp = strtok(NULL, delim); 
     counter++; 
    } 

    if(strncmp(*tokens, cd_command, strlen(cd_command)) == 0) { 
     path_len = strlen(*(tokens+1)); 
     strncpy(path, *(tokens+1), path_len-1); 
    // this is where I try to remove the trailing junk... 
    // but it doesn't work on a second system 
     if(chdir(path) < 0) { 
      error_string = strerror(errno); 
      fprintf(stderr, "path: %s\n%s\n", path, error_string); 
} 

// just to check if the chdir worked 
char buffer[1000]; 
    printf("%s\n", getcwd(buffer, 1000)); 

    } 

    return 0; 
} 

더 좋은 방법이 있어야합니다. 어떤 도움을 줄 수 있습니까? I'vr은 scanf를 사용하려고했지만 프로그램이 scanf를 호출하면 멈 춥니 다. 당신이를 strncpy를 호출 한 후 경로 문자열에 널 (null) '\ 0'을 추가 할 잊어 버린 것 같습니다

감사

답변

5

(). null 종결자가 없으면 chdir()은 문자열이 어디에서 끝나는 지 알지 못합니다. 이렇게하면 경로 끝에 여분의 문자가있는 것처럼 보입니다.

+0

아 예. 어리석은 실수 야. 고마워. 나는 꽤 좌절하고 있었다. – devin

+0

내가 바보 프로그래밍 실수를 할 때마다 니켈을 가지고 있다면 ... –

3

예를 들어 문제가 2 개 이상입니다.

첫 번째 문제 (즉각적인 명백한 문제를 일으키는)는 strncpy()의 사용으로, '\ 0'종결자를 복사 할 버퍼의 끝에 넣지 않아도됩니다. 귀하의 경우에는 strncpy()을 사용할 필요가 없습니다 (정확하게 당신이 도망친 이유 때문에 위험하다고 생각합니다). 토큰은 strtok()으로 끝나는 '\ 0'이되며 토큰은 경로 버퍼와 같은 크기의 버퍼에서 생성되므로 경로 버퍼보다 ​​작을 수 있습니다. strcpy()을 사용하거나 나중에 코드를 가져 오는 사람이 코드를 복원하고 버퍼 크기를 mucking하려는 경우 비표준 strlcpy()과 같은 것을 사용하십시오.

어림짐작으로 strncpy()을 사용하지 마십시오.

코드의 또 다른 문제점은 tokens 할당이 올바르지 않다는 것입니다.

char** tokens = (char**) malloc(sizeof(char)*IN_LEN); 

은 입력 문자열 버퍼와 같은 대형으로 영역을 할당합니다,하지만 당신은 문자, 즉 할당에 문자열에 대한 포인터를 저장하지 않는 것입니다. 문자보다 정의 토큰 수가 적지 만, 각 토큰 포인터는 문자보다 4 배 더 큽니다 (플랫폼의 포인터 크기에 따라 다름). 문자열에 토큰이 충분하면이 버퍼를 오버런시킵니다.

예를 들어, IN_LEN이 14이고 입력 문자열이 "a b c d e f g"라고 가정합니다. 공백을 구분 기호로 사용하면 7 개의 토큰이 생겨 28 바이트의 포인터 배열이 필요합니다. 꽤 많은 숫자가 malloc()에 의해 할당 된 14 개보다 많습니다. 에

간단한 변화 :

char** tokens = (char**) malloc((sizeof(char*) * IN_LEN)/2); 

충분한 공간을 할당해야 (? 거기 off-by-one 오류가 아마 +1 필요).

세 번째 문제는 배열에 0 개 또는 하나의 토큰 만 추가 된 경우에도 *tokens*(tokens+1)에 액세스 할 수 있다는 것입니다. 이러한 포인터를 역 참조하기 전에 counter 변수의 검사를 일부 추가해야합니다.