2017-01-07 79 views
-3

我編寫了一個程序,它從標準輸入中讀取一條命令行,並將其傳遞給應該解析爲標記的函數。爲什麼我的解析函數不返回所有預期的標記?

這是解析函數:

char** parse_cmdline(char* cmdline) { 
    char ** arr = malloc(10 * sizeof(char*)); 
    for (int i =0 ; i < 10; ++i) 
     arr[i] = malloc(30 * sizeof(char)); 
    char * token = strtok(cmdline, " "); 
    int i = 0; 
    while(token != NULL) { 
     if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*)); 
     arr[i] = token; 
     token = strtok(NULL, " "); 
     i++; 
    } 
    printf("flag1"); 
    return arr; 
} 

這是我如何使用它,它main()

int main() { 
    int status; 
    pid_t pid; 
    pid = fork(); 

    while(1) {  
     if(pid < 0) { 
      status = -1; 
      perror("Fork"); 
     } else if(pid == 0) { 
      char* cmd; 
      printf("$"); 
      if(fgets(cmd, sizeof cmd, stdin) == NULL) break; 
      parse_cmdline(cmd); 
     } else { 
      if(waitpid(pid, &status, 0) != pid) { 
       status = -1; 
      } 
      break; 
     } 
    } 


    return 0; 
} 

這是我提供給我的程序輸入的例子:

ls l a 

預期產出應該是:

l 

(也就是第二個參數,通過我的解析函數打印)

字面上沒有任何反應。甚至沒有printf(「flag1」);打印。但是,如果我刪除char ** commands並將printf("%s", commands[0]);放在parse_cmdline函數中,除im未分配返回值外,其他所有函數都可以正常工作。爲什麼以及如何解決它?


按照要求,這裏是我的代碼全部:

#include <stddef.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

char** parse_cmdline(char* cmdline) { 
    char ** arr = malloc(10 * sizeof(char*)); 
    for (int i =0 ; i < 10; ++i) 
     arr[i] = malloc(30 * sizeof(char)); 
    char * token = strtok(cmdline, " "); 
    int i = 0; 
    while(token != NULL) { 
     if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*)); 
     arr[i] = token; 
     token = strtok(NULL, " "); 
     i++; 
    } 
    printf("%s\n", arr[1]); 
    return arr; 
} 
+0

發佈一個最小的,完整的,可驗證的例子。 – EOF

+0

你還需要什麼? –

+0

我可以粘貼到一個文件並進行編譯,加上一個輸入,我可以將其輸入到編譯結果中。可能是一個輸出,我可以比較程序運行的輸出。 – EOF

回答

1

這部分看起來很奇怪 - 看評論在線:

char ** arr = malloc(10 * sizeof(char*)); 
for (int i =0 ; i < 10; ++i) 
    arr[i] = malloc(30 * sizeof(char));  // Here you allocate memory 
              // for holding a part of the command 

char * token = strtok(cmdline, " "); 
int i = 0; 
while(token != NULL) { 
    if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*)); 

    arr[i] = token;    // But here you overwrite the pointer value and 
           // and thereby create a memory leak 

    token = strtok(NULL, " "); 
    i++; 
} 

也許你想做一個字符串拷貝代替 - 這樣的:

strcpy(arr[i], token); // Instead of arr[i] = token; 

此外,該行似乎有些奇怪:

if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*)); 

您增加arr,以便它可以容納更多char*但這個t ime你不會像最初那樣爲新字符串分配內存。

0

首先,你是不是分配空間的命令。的cmd聲明更改爲這樣的事情:

char cmd[100]; 

不分配內存會導致不確定的行爲,而這(的fgets修補程序,以及與正確使用)。但你也應該從fgets()檢查100個字符是不夠的:

if (strstr(cmd, "\n") == NULL) { 
    /* the user typed more than 100 characters */ 
} 

因爲如果他們還不夠,那麼你要分析一個不完整的命令行,下一次在輸入數據的循環迭代,它會解析更多不完整的命令。

最後,strtok返回指針指向令牌cmd,所以所有這些字符數組,你在你的解析函數的開頭分配了內存泄漏,因爲你的指針從strtok取而代之內循環:

arr[i] = token; 
/* this throws away the address of the 10-character array you allocated 
* at the beginning of the function. You can't free() that memory 
* anymore. Your program is "leaking" memory. */ 

嚴格來說,順便說一下,您應該檢查realloc是否返回有效地址或NULLmalloc。在這樣一個小程序中,你不太可能會遇到問題,但這是正確的做法。

您還應該在使用過後解決已分析的命令。你分配一個指針數組mallocrealloc,但你從來沒有free他們在你的程序。即使程序即將結束,但程序正在運行,這就是內存泄漏。 (再次,不太可能你會看到一個小程序的問題,但這是一個好習慣。)

相關問題