2010-05-25 70 views
3

以下代碼片段在爲最後一個arg分配內存時會出現分段錯誤。我究竟做錯了什麼?謝謝。將數組的內存分配給字符指針

int n_args = 0, i = 0; 
    while (line[i] != '\0') 
    { 
     if (isspace(line[i++])) 
      n_args++; 
    } 

    for (i = 0; i < n_args; i++) 
     command = malloc (n_args * sizeof(char*)); 

    char* arg = NULL; 
    arg = strtok(line, " \n"); 
    while (arg != NULL) 
    { 
     arg = strtok(NULL, " \n"); 
      command[i] = malloc ((strlen(arg)+1) * sizeof(char)); 
     strcpy(command[i], arg); 
     i++; 
    } 

謝謝。

回答

4

您不會在for循環後重置i的值,因此當您到達底部塊時,i等於n_args。試圖在此時訪問command[i],以訪問未初始化的內存和段錯誤。

這裏真正的教訓是不要在沒有充分理由的情況下以這種方式重用變量。如果您在中間for循環中使用i以外的其他代碼,則您的代碼將更加健壯,更易於閱讀。

+1

好讀書,那個。 – dmckee 2010-05-25 18:39:03

0

對於包含由單個空格分隔的兩個參數的行,n_args將爲1而不是2.這可能不是您想要的。

2
for (i = 0; i < n_args; i++) 
     command = malloc (n_args * sizeof(char*)); 

應該成爲只是

command = malloc (n_args * sizeof(char*)) 

,因爲你只想ALLOC n_args元素的數組,並

while (arg != NULL) 
    { 
     arg = strtok(NULL, " \n"); 
     command[i] = malloc ((strlen(arg)+1) * sizeof(char)); 
     strcpy(command[i], arg); 
     i++; 
    } 

應該變成:

arg = strtok(NULL, " \n"); 
while (arg != NULL) { 
    command[i] = malloc ((strlen(arg)+1) * sizeof(char)); 
    strcpy(command[i], arg); 
    i++; 
    arg = strtok(NULL, " \n"); 
} 

避免的strlen在空指針上。

+0

把strtok(NULL)放在最後避免跳過第一個參數 – 2010-05-25 18:55:56

+0

另外我應該在循環前重置爲0 while(arg!= NULL)... – 2010-05-25 22:53:16

0

我想你在這裏有一些有趣的事情(如果我正確閱讀這個)。

塊:

for (i = 0; i < n_args; i++) 
    command = malloc (n_args * sizeof(char*)); 

應該是這樣的:

command = malloc (n_args * sizeof(char*)); 

無需一遍又一遍的重新分配command

至於seg故障,可能是因爲您正在重新使用變量i,而無需再次將其重置爲零。

0

你正在扔掉你的第一個arg?那是故意的嗎?在不是的情況下

int n_args = 1;  /* We need one element more than spaces */ 
int i = 0; 
while (line[i]) 
{ 
    if (isspace(line[i++])) 
     n_args++; 
} 

command = malloc (n_args * sizeof(char*)); 

char* arg = NULL; 
arg = strtok(line, " \n"); 
i = 0;  /***** You forgot to reset that value, that was your segfault !!! */ 
while (arg) 
{ 
    command[i++] = strdup(arg); /* It does your malloc/strlen/strcpy */ 
    arg = strtok(NULL, " \n"); 
} 

你忘了重置你的i索引,它在你的代碼中到達你分配的數組之外。

+0

我把它作爲註釋加入,不想要重新編輯我的答案小問題,重用變量用於不同的目的是不好的方式,你在3個不同的地方重複使用i,其中2個索引相同的東西,所以它在我眼中是可以的第一個​​用法是不同的,index在語法上不同的'line'上,我會使用另一個變量,它對編譯器沒有任何影響,但是如果變量不在中間改變角色,它會更容易閱讀。 – 2010-05-25 18:52:16

0

儘量合理安排這個循環:

while (arg != NULL) 
    { 
     arg = strtok(NULL, " \n"); 
      command[i] = malloc ((strlen(arg)+1) * sizeof(char)); 
     strcpy(command[i], arg); 
     i++; 
    } 

行 「ARG = strtok的......」 做兩個事情冤屈:

  1. 跳過第一個參數。
  2. 不檢查返回碼,所以如果arg == NULL,那麼strlen(arg)將會SEGFAULT。

而是執行此操作:

while (arg != NULL) 
    { 
     command[i] = malloc ((strlen(arg)+1) * sizeof(char)); 
     strcpy(command[i], arg); 
     i++; 
     arg = strtok(NULL, " \n"); 
    } 
0

很難找出你正在嘗試做的。

看起來您正在查看命令行中的空格數,以查看您有多少個命令行參數。你所有的命令行都是單個字符嗎? malloc只爲每個arg的一個字符保留足夠的空間。

如果您的ARG遊戲只是每一個字符:

command = malloc(strlen(line)); 
i = 0; 
j = 0; 
while(line[j]) { 
    if(!isspace(line[j])){ 
     command[i++] = line[j]; 
    } 
    j++; 
}