【问题标题】:Does the order I declare pointers really matter in C? getcwd() problem我声明指针的顺序在 C 中真的很重要吗? getcwd() 问题
【发布时间】:2010-04-12 00:40:48
【问题描述】:

在 Solaris 5.8 机器上,我有以下代码:

[无效代码]

char *buf;
char *dir;
size_t psize;

psize = (size_t) 1024;
dir = getcwd(buf, psize);

在这台 unix 机器上,上述操作不起作用,我在尝试运行程序时遇到了分段错误。仅当我声明 dir before buf:

时才有效

[工作代码]

char *dir;
char *buf;
...
dir = getcwd(buf, psize);

当使用另一种风格的 Unix 时,例如 Mac OS X,我没有得到任何关于如何编写代码的似乎非常严格的规则。谁能解释上面的例子发生了什么?谢谢!

【问题讨论】:

    标签: c unix getcwd


    【解决方案1】:

    来自getcwd(3):

    描述
         getcwd() 函数复制当前工作的绝对路径名
         将目录放入 buf 引用的内存中,并返回一个指向 buf 的指针。
         size 参数是 buf 引用的数组的大小(以字节为单位)。
    
         如果 buf 为 NULL,则根据需要分配空间来存储路径名。
         这个空间稍后可能会被释放(3)。
    
    

    即 - 完成后将 buf 设置为 NULL 和 free(3) dir; 或你自己为buf分配空间(因为你告诉getcwd(3)你有1K)。

    编辑:

    所以要稍微清理一下,可以是:

    char *dir = getcwd( NULL, 0 );
    
    if ( dir == NULL ) { /* handle error */ }
    /* use dir */
    free( dir );
    

    或

    char buf[1024]; /* or allocate it with malloc(3) */
    
    if ( getcwd( buf, 1024 ) == NULL ) { /* handle error */ }
    
    /* use buf, DO NOT free it if it's on the stack or static, 
       only if malloc-ed */
    

    【讨论】:

    • 谢谢,清空它的工作。我还读到 getcwd() 为缓冲区分配了内存,所以我并不担心自己分配它。我正在阅读,但想知道 - 是否有一个规则,当你初始化一个指向 NULL 的指针而不是等待分配指针?
    • 没有隐含的规则。每个功能都不同 - 请阅读手册页。说,这里的答案很容易在man getcwd 中找到。
    • @chucknelson:大多数函数不会为你分配内存,所以规则是,提前自己分配指针。否则,您将垃圾传递给需要有效 char*-buffer 的函数。
    • 你根本不需要变量buf;只需写NULL 作为第一个参数。因为 C 总是按值传递参数,所以作为参数传递给函数的任何变量都必须首先初始化。
    【解决方案2】:

    POSIX requires 第一个参数是指向存储路径名的缓冲区的指针。 Mac OS X、Linux、Solaris 和其他系统上存在的一个常见扩展是,如果第一个参数为 NULL,则 getcwd() 将使用 malloc() 为您分配一个缓冲区 - 然后您将使用 @ 释放它987654324@ 完成后。 POSIX 允许此扩展,但不是必需的,因此您不应在可移植代码中依赖它。

    在您的情况下,您将一个未初始化的值作为第一个参数传递给getcwd()。如果它恰好等于 NULL,那么将分配一个缓冲区;如果它是其他一些无效指针,那么您可能会遇到分段错误。由于该值未初始化,因此它可以具有任何值,并且可能取决于声明的顺序。如果您打算由getcwd() 分配缓冲区,则显式传入值NULL;没有必要为此声明一个变量。然而,更便携的解决方案是传递一个指向您自己的缓冲区的指针,而不是依赖此扩展。

    【讨论】:

      【解决方案3】:

      您只声明了一个指针,并没有分配任何内存供 getcwd 写入。 getcwd 不会为您分配内存。需要自己调用malloc来分配。

      【讨论】:

        【解决方案4】:

        您声明指针的顺序将决定它们在内存堆栈中的放置顺序。我的猜测是,从buf 的地址开始存在缓冲区溢出,这在示例一但不是示例二中破坏了dir。您的其他操作系统可能会以静默方式阻止此错误或以不同方式处理它。

        【讨论】:

          【解决方案5】:

          声明顺序无关。

          char *getcwd(char *buf, size_t size);
          
          getcwd() 函数复制当前工作的绝对路径名
          **buf**指向的数组的目录,长度为**size**。

          buf 应该在使用前分配内存。

          buf = malloc(length * sizeof(char));
          

          char *buf; 执行后,buf 包含垃圾值,当getcwd() 尝试修改指向的内存 bu buf 时,会导致Segmentation Fault。

          【讨论】:

            猜你喜欢
            • 2011-12-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多