为char指针分配数组内存

3
下面这段代码在为最后一个参数分配内存时会导致分段错误。我做错了什么?谢谢。
    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++;
    }

感谢您的选择。
7个回答

4
您在 for 循环后没有重置 i 的值,所以当您到达底部块时,i 等于 n_args。此时尝试访问 command[i] 将访问未初始化的内存并导致段错误。
真正的教训是不要在没有充分理由的情况下以这种方式重复使用变量。如果您在中间的 for 循环中使用其他变量而不是 i,那么您的代码将更加健壮且易于阅读。

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

应该只变成

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

因为你只想要分配一个包含 n_args 元素的数组,而

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

should become:

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,请进行以下操作。

strtok(NULL 放在末尾也可以避免跳过第一个参数。 - Patrick Schlüter

0
我认为你在这里有一些有趣的事情(如果我正确地阅读了这个)。
这个块:
for (i = 0; i < n_args; i++)
    command = malloc (n_args * sizeof(char*));

应该是这样的:

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

不需要一遍又一遍地重新分配command

至于段错误,可能是因为您在没有将i变量重新设置为零的情况下重复使用它。


0
你丢弃了第一个参数?这是有意为之吗?如果不是的话
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 索引,导致它超出了你代码中分配的数组范围。


我将其作为注释添加,不想重新编辑我的答案。小问题是,重复使用变量以达到不同的目的是不好的风格,您在3个不同的地方重复使用了i,在其中2个地方它索引了相同的内容,所以在我看来这是可以的。第一次使用是不同的,在line上进行索引,这在语义上是不同的,我会使用另一个变量代替。对于编译器来说不会有任何区别,但如果变量在中间不改变角色,则阅读起来会更容易。 - Patrick Schlüter

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 只为每个参数保留了足够的空间来存储一个字符。

如果你的参数只有一个字符:

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

0

对于由单个空格分隔的两个参数组成的行,n_args 将为 1 而不是 2。这可能不是您想要的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接