【问题标题】:Allocating memory for a array to char pointer将数组的内存分配给 char 指针
【发布时间】:2011-02-23 20:14:52
【问题描述】:

以下代码在为最后一个 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++;
    }

谢谢。

【问题讨论】:

    标签: c pointers multidimensional-array memory-management


    【解决方案1】:

    for 循环之后,您不会重置i 的值,因此当您到达底部块时,i 等于n_args。此时尝试访问command[i] 会访问未初始化的内存和段错误。

    这里真正的教训是不要在没有充分理由的情况下以这种方式重用变量。如果您在中间的 for 循环中使用 i 以外的其他内容,您的代码将更加健壮且更易于阅读。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:
        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++;
            }
        

        应该变成:

        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 放在最后避免也跳过第一个参数。
        【解决方案4】:

        我认为这里发生了一些有趣的事情(如果我没看错的话)。

        这个区块:

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

        应该是这样的:

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

        无需一遍又一遍地重新分配command

        至于 seg 错误,可能是因为您重新使用了 i 变量,而没有先将其重新设置为零。

        【讨论】:

          【解决方案5】:

          你要扔掉你的第一个参数?这是故意的吗?如果不是

          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 上的索引在语义上不同,我会使用另一个变量。它对编译器没有任何影响,但是如果变量在中间不改变角色会更容易阅读。
          【解决方案6】:

          尝试正确安排这个循环:

           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");
              }
          

          【讨论】:

            【解决方案7】:

            很难弄清楚你想做什么。

            看起来您正在查看命令行中的空格数,以查看您有多少命令行参数。你所有的命令行参数都是一个字符吗? malloc 只为每个 arg 一个字符保留足够的空间。

            如果您的 args 每个只有一个字符:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-10-06
              • 2011-04-02
              • 1970-01-01
              • 2015-10-26
              • 2019-01-10
              • 1970-01-01
              • 2021-04-13
              • 2020-06-01
              相关资源
              最近更新 更多