2013-01-20 100 views
1

在我的C程序中,我使用execvp命令來解析輸入並運行它。 我有這樣的:execvp導致內存問題

char read_str[MAX_ALLOWED_BUFFER]; 
pid_t child_pid; 
char *strs[100] = {NULL}; 

child_pid = fork(); 
if (child_pid == 0) { 
    split(read_str, strs); 
    execvp(strs[0], strs); 
    printf("Failed\n"); 
} 
else { 
    waitpid(child_pid, NULL, 0); 
    for (y = 0; y < 100; y++) free(strs[y]); 
} 

和該功能

void split(char *str, char **splitstr) {  
    char *p;  
    int i=0;  
    p = strtok(str," "); 
    while(p!= NULL) {   
     splitstr[i] = malloc(strlen(p) + 1); 
     if (splitstr[i]) strcpy(splitstr[i], p); 
     i++; 
     p = strtok(NULL, " ");  
    } 
} 

第一碼塊是在while循環和不斷要求用戶輸入。無論如何,如果execvp返回,然後出現錯誤,它打印失敗,然後如果我鍵入兩個更有效的命令,我得到一個內存損壞錯誤...

有沒有人看到我在做什麼錯在這裏?

+1

*「我使用execvp命令來解析輸入並運行它。」*以這種方式使用未經過濾的用戶輸入是一個令人難以置信的糟糕主意。如果我將您的程序'rm -rf〜/'或將Little Bobby Tables的名稱傳遞給您的大型生產數據庫,該怎麼辦? – dmckee

+0

假設正在構建的程序是一個外殼,看起來是這樣的:外殼應該這樣做。這點很重要。除非有一些更大的上下文表明來自** untrusted **用戶的輸入涉及,否則不要在這裏假設安全問題。 – duskwuff

回答

0

我在做什麼錯在這裏

幾件事情。

  • execvp失敗,孩子轉到while循環的開始,現在你有兩個孩子和家長閱讀輸入。你想要做的是exit(1)印刷後"Failed"
  • 如果你這樣做,那麼strs永遠不會在父級中分配,並且不需要是free() d。您可以將strs的定義移動到if (child_pid == 0) {中,並且您從不需要擔心任何事情。

這並不說明你的內存損壞問題,這是這樣的:

  • 失敗execvp離開孩子C1讀取輸入。 C1在其strs陣列中有malloc()編輯條目。
  • now C1得到輸入,fork() s C2waitpid s。然後C1調用freestrs條目,他們成爲懸掛(你應該NULL他們出)。
  • 現在C1再次獲取輸入,fork小號C3waitpid S代表它,並再次呼籲相同strsfree,導致雙free,並且已經觀察到腐敗。