2010-05-25 69 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++; 
}