【问题标题】:Unable to pass char pointer to gethostname (Linux)无法将 char 指针传递给 gethostname (Linux)
【发布时间】:2013-12-27 07:39:32
【问题描述】:

以下 C 程序尝试获取并打印当前 RHEL 主机的主机名。它会在这台机器上抛出一个segmentation fault。根据gethostname 的定义,我应该能够传递一个字符指针,不是吗?

当我改用 char 数组(如 char hname[255])时,对 gethostname 的调用有效。 (如果我这样做,我将如何将数组返回到 main?)

#include <stdio.h>
#include <unistd.h>
char * fetchHostname()
{

    // using "char hname[255]" gets me around the issue;
    // however, I dont understand why I'm unable to use
    // a char pointer.

    char *hname;
    gethostname(hname, 255 );

    return hname;

}

int main()
{
    char *hostname = fetchHostname();
    return 0;
}

输出:

pmn@rhel /tmp/temp > gcc -g test.c -o test
pmn@rhel /tmp/temp >

pmn@rhel /tmp/temp > ./test
Segmentation fault
pmn@rhel /tmp/temp >

【问题讨论】:

    标签: c hostname rhel unistd.h


    【解决方案1】:

    正如gethostname男人所说:

    gethostname() 函数应返回标准主机名 当前机器。 namelen 参数应 指定 name 参数指向的数组的大小。 返回的名称应以 null 结尾,除了 如果 namelen 的长度不足以容纳主机名, 然后返回的名称将被截断,它是 未指定返回的名称是否以 null 结尾。

    你需要一个地方来存储函数信息,所以将主机名声明为一个数组,而不是一个指针。

    #include <unistd.h>
    
    char * fetchHostname(char *hostname, int size)
    {
    
        // using "char hname[255]" gets me around the issue;
        // however, I dont understand why I'm unable to use
        // a char pointer.
        gethostname(hostname, size);
    
        return hostname;
    }
    
    int main()
    {
        char hostname[HOST_NAME_MAX + 1];
    
        fetchHostname(hostname, HOST_NAME_MAX);
        return 0;
    }
    

    【讨论】:

    • 您的回答是正确的,尽管我认为这不会消除他的困惑。也许添加一段解释 char* hostname 需要是指向字符串需要去的地方的指针,而不是任何旧的 char* 将是有益的。我认为他的错误表明他是一个新手,需要更彻底地解释代码的作用。
    • 我同意,这是因为我添加了男人信息:the namelen argument shall specify the size of the array pointed to by the name argument
    • 谢谢@Tio。我现在明白了。
    • 1+ 用于使用HOST_NAME_MAX
    【解决方案2】:

    当我改用 char 数组(如 char hname[255])时,调用 gethostname 有效。 (如果我这样做,我将如何将数组返回到 主要?)

    通过将指向数组的指针从main() 传递给您的函数。请注意,这种方法使您的函数 fetchHostname() 只是函数 gethostname() 的包装器:

    #include <stdio.h>
    #include <unistd.h>
    void fetchHostname(char *hname)
    {
        gethostname(hname,255);
    }
    
    int main()
    {
        char hostname[256];
    
        fetchHostname(hostname);
        return 0;
    }
    

    或者通过声明你的hname[]数组本地静态,所以即使在程序离开函数后它也是有效的(这种方法不是线程安全的):

    #include <stdio.h>
    #include <unistd.h>
    
    char *fetchHostname (void)
    {
        static char hname[256];
    
        gethostname(hname,255);
        return hname;
    }
    
    int main()
    {
        char *hostname;
    
        hostname = fetchHostname();
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      虽然有很多技术上正确的答案,但我认为它们实际上并没有向你解释你哪里出错了。

      gethostname(char *name, size_t len); 记录在here 中,它基本上说参数name 是一个字符数组您已分配,此函数会将主机名复制到其中。您如何做到这一点在此处的许多其他精彩答案中进行了说明。

      这就是为什么如果你自己创建数组,但如果你只给它一个指针就会导致分段错误。

      另外,你给这个函数一个未初始化的指针,所以当它试图将数据复制到那个地址(这只是内存中的某个完全随机的地方)时,它会导致你的程序终止,因为它试图在它的位置写入一个字符串不允许。

      这种类型的错误告诉我,您需要重新了解指针实际上是什么,并且您需要了解它们可用于允许函数以与使用 return 语句不同的方式返回值.

      【讨论】:

      • 感谢@nonsensickle 的解释。
      【解决方案4】:

      更新:请参阅@Tio Pepe 的回答。

      您需要在数组中分配空间(静态或动态):

      char hname[HOST_NAME_MAX + 1];
      

      否则,您将传递一个可能指向任何地方的未初始化指针。

      您对 gethostname() 的调用:

       gethostname(hname, 255);
      

      是一个契约,这里说的是一个指向至少 255 个字符的已分配空间的指针。

      此外,您正在尝试返回指向堆栈上分配空间的指针。这不好。

      如果要返回,需要动态分配字符数组。

      char * hname;
      hname = malloc((HOST_NAME_MAX +1) * sizeof(char));
      

      但请注意,您现在必须管理何时释放该空间。

      【讨论】:

      • 谢谢@Mitch。我意识到这行得通;但不知道如何将其返回给main。顺便说一句,这是否意味着在函数中使用 char 指针作为参数是永远安全的?
      • char 指针只要指向你拥有的空间就可以了。
      • 你能告诉我如何将char数组传递给main吗?
      • 应该是malloc(256);。另请注意,sizeof(char) 定义为 1。
      【解决方案5】:

      返回指向局部变量的指针是未定义的行为,因为它会超出范围。如果在堆上分配(通过动态分配),就不会有这个问题。

      char * fetchHostname()
      {
          char* hname= malloc(sizeof(char) * 256);
          gethostname(hname, 255);
      
          return hname;
      }
      
      int main()
      {
          char *hostname = fetchHostname();
          printf(hostname);
          free(hostname);
          return 0;
      }
      

      【讨论】:

      • 代码应该为0-terminator再分配1个然后告诉函数填充:... = malloc(256);sizeof(char)被定义为1。
      【解决方案6】:
      char *hname; //defined inside a function and would be destroyed after the function is executed
      

      fetchHostname() 执行后返回给主机名的地址无效,访问它会导致分段错误

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-07
        • 2018-08-11
        • 2016-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多