【问题标题】:Using malloc properly正确使用 malloc
【发布时间】:2014-03-25 01:11:10
【问题描述】:

我正在尝试将我的目录路径名放在一个字符串变量上,如下所示:

int main(int ac, char **av)
{
  char*dir;

  if(ac > 2)
    {
      dir = malloc(sizeof(*dir) * 512);
      getcwd(dir, sizeof(*dir));
      printf("dat dir is:\n");
      printf("%s\n", dir);
    }
}

我打印了一个空白,但是当我这样做时

int main(int ac, char **av)
{
  char dir[512];

  if(ac > 2)
    {
      // dir = malloc(sizeof(dir) * 512);                                                                
      getcwd(dir, sizeof(dir));
      printf("dat dir is:\n");
      printf("%s\n", dir);
    }
}

打印正确,为什么?我的第一个 malloc 不是应该让我的变量像 dir[512]

【问题讨论】:

    标签: c unix getcwd


    【解决方案1】:

    getcwd(dir, sizeof(*dir))
    

    sizeof 产生 1,因为 *dir 指的是单个 char。这不是你想要的。如果你用 512 替换它,应该一切正常。

    惯用的编码是这样的:

    int main(int ac, char **av)
    {
      const int buf_size = 512;
      char *dir;
    
      if(ac > 2)
        {
          dir = malloc(buf_size);
          getcwd(dir, buf_size);
          printf("dat dir is:\n");
          printf("%s\n", dir);
        }
    }
    

    注意乘以sizeof(*dir) 是一个空操作,因为它总是返回1。也就是说,mallocchar 为单位进行分配。所以我省略了无操作。

    【讨论】:

    • 我放了 512,谢谢,512 在 unix 上够用吗?以及为什么它不打印路径的第一个字符,如果它是 1 ?
    • 这因系统而异。对于 Linux,它显然是 4096。请参阅 cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/…。但我不是 Linux 专家。
    • 当大小为 1 时,getcwd() 唯一能做的就是在字符串中放入空终止符。当它为0时,它甚至不能这样做。
    【解决方案2】:

    这与数组、指针和sizeof的含义有关。

    char dir[512];
    sizeof(dir);
    

    这是询问数组的大小,在本例中为 sizeof(char) * 512 -> 512

    char *dir;
    sizeof(dir);
    

    这是询问指针的大小,在本例中为sizeof(char *) -> 48

    char *dir;
    sizeof(*dir);
    

    这是一个奇怪的结构。我真的不舒服。因为dir 尚未初始化,所以dir 的任何取消引用都值得关注。但我认为编译器在这里解决了正确的问题,在这种情况下是 sizeof(char) -> 1

    当使用 if 指针时,你需要携带你分配的大小。

    char*dir;
    if(ac > 2)
    {
        dir = malloc(sizeof(char) * 512);
        getcwd(dir, sizeof(char) * 512);
        printf("dat dir is:\n");
        printf("%s\n", dir);
    }
    

    正确答案™有点复杂。

    if (ac > 2)
    {
        size_t size = 512;
        char *buf = malloc(size);
        char *dir = getcwd(buf, size);
    
        while (dir == NULL && errno == ERANGE)
        {
            size *= 2;
            buf = realloc(buf, size);
            dir = getcwd(buf, size);
        }
    
        printf("dat dir is:\n");
        printf("%s\n", dir);
        free(buf);
    }
    

    首先,我放弃sizeof(char)。在 C 中,sizeof(char) 被定义为1,所以它是多余的。接下来,将dir设置为getcwd(3)的返回值,并将数据缓冲区分开。一定要检查返回值,如果getcwd(3) 返回NULL 并且errnoERANGE 那么buf 不够大。在我的示例中,我在再次尝试getcwd(3) 之前将缓冲区的大小加倍。最后别忘了免费buf

    我没有在这里做的是检查malloc(3)realloc(3) 的返回值。这是因为我觉得这个例子没有意义。如果我不能分配路径的大小,那么无论我做什么,我的程序都会崩溃。

    【讨论】:

      【解决方案3】:

      如果您尽早将大小放入变量中然后使用它,那么出错的可能性就会减少:

      { 常量 sizeof_dir = sizeof(*dir)*512; 目录 = malloc(sizeof_dir); getcwd(目录,sizeof_dir); printf("dat 目录是:\n"); printf("%s\n", 目录); }

      杀死你的是getcwd(dir, sizeof(*dir)),它的sizeof仍然是1。

      【讨论】:

        【解决方案4】:

        每当您动态分配内存时,请始终检查 calloc、malloca 和 realloc 的返回值,因为返回值表明内存分配成功与否。这里上述第一个答案很好,检查返回值总是有帮助的。

        【讨论】:

          猜你喜欢
          • 2012-01-05
          • 1970-01-01
          • 2015-07-20
          • 2020-08-26
          • 1970-01-01
          • 2014-03-08
          相关资源
          最近更新 更多