有人可以帮我理解如何在c中正确分配?

时间:2010-09-30 22:04:43

标签: c memory-management

我认为我没有正确理解如何为我想做的事情分配内存。

我希望我的程序将命令行中的参数存储到名为Command的stuct数组中,其中包含char ** args。例如,如果我运行

./test.c echo hello : ls -l

我想将它存储为

commands[0].args[0]= echo
commands[0].args[1]= hello
commands[1].args[0]= ls
commands[1].args[1]= -l

但我的代码却以这种方式存储

commands[0].args[0]= echo
commands[0].args[1]= hello
commands[0].args[2]= ls
commands[0].args[3]= -l
commands[1].args[0]= ls
commands[1].args[1]= -l

有人可以帮我理解为什么它会在两个地方存储ls -l吗?这是我的代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

typedef struct test {
   char **args;
} Command;


int main(int argc, char *argv[])
{
   int i, j, k;
   Command *commands;

   j = k = 0;
   commands = (Command *)malloc(argc * sizeof(Command));

   for (i = 1; i < argc; i++)
   {
      if (strcmp(argv[i], ":") == 0)
      {
         j++;
         k = 0;
      }
      else {
         commands[j].args = (char **)realloc(commands[j].args, (k+1) * sizeof(char*));
         commands[j].args[k++] = argv[i];
      }
   }

   for (i = 0; i <= j; i++)
   {
      for (k = 0; k < 5; k++)
      {
         printf("commands[%d].args[%d]= %s\n", i, k, commands[i].args[k]);
      }
   }
   return EXIT_SUCCESS;
}

4 个答案:

答案 0 :(得分:1)

您的数据存储结构无法告知commands[j]中有多少字符串有效。所以我认为它正在commands[0]commands[1]分别提出两个指针,就像你期望的那样。但是,然后你的打印循环会查看commands[0].args[k]的k一直到4,尽管它只对前两个有效。当你开始查看commands[0].args[2]时,结果是未定义的。 (如果您使用未定义的行为,则显示程序中其他位置的内存,崩溃和着火只是程序允许执行的一些操作。)

要确定每个命令中有多少个参数,您可以向struct test添加一个计数器成员。或者可能再分配一个指针而不是参数,并在最后一个参数后面加上一个NULL。

答案 1 :(得分:0)

您的每个Command结构只有一个arg

也许你应该考虑

typedef struct test {
   char **args[5];
} Command;

然后设计一个更好的数据结构,如列表列表。

答案 2 :(得分:0)

也许你应该在结构中存储args的长度?

typedef struct test {
    char ** args;
    unsigned length;
} Command;

另外,也许你应该考虑使用C字符串库的一些内置功能。例如,strtok使用您提供的分隔符拆分字符串。

答案 3 :(得分:0)

以下是我如何分配内存:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct cmd_s {
    int num;
    char **args;
} cmd_t;

void print_cmds(cmd_t *c, int num) {
    int i, j;
    for (i=0;i<=num;i++) {
        for (j=0;j<c[i].num;j++)
            printf("cmds[%d][%d] = %s\n", i, j,c[i].args[j]);
    }
}

int main(int argc, char *argv[]) {
    int i, j = 0, k = 0;
    cmd_t *cmds;

    cmds = (cmd_t *)malloc(sizeof(cmd_t));
    cmds[0].args = NULL;
    cmds[0].num = 0;

    for (i=1;i<argc;i++) {
        if (strcmp(argv[i], ":") == 0) {
            cmds = (cmd_t *)realloc(cmds, (sizeof(cmd_t) * ++j) + 1);
            cmds[j].args = NULL;
            cmds[j].num = 0;
            continue;
        }
        cmds[j].args = (char **)realloc(cmds[j].args, sizeof(char *) * ++cmds[j].num);
        cmds[j].args[cmds[j].num-1] = (char *)malloc(50);
        strcpy(cmds[j].args[cmds[j].num-1], argv[i]);
    }

    print_cmds(cmds, j);

    for (i=0;i<=j;i++) {
        for(k=0;k<cmds[i].num;k++)
            free(cmds[i].args[k]);
        free(cmds[i].args);
    }

    free(cmds);
    return 0;
}