0

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

当我改用 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 >
4

6 回答 6

3

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

通过将指向数组的指针传递main()给您的函数。请注意,这种方法使您的函数fetchHostname()只是 function 的包装器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;
}
于 2013-12-27T07:51:10.850 回答
3

正如gethostname男人所说:

gethostname() 函数应返回当前机器的标准主机名。namelen 参数应指定 name 参数指向的数组的大小。返回的名称应以空结尾,除非 namelen 的长度不足以容纳主机名,则返回的名称应被截断,并且未指定返回的名称是否以空结尾。

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

#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;
}
于 2013-12-27T07:46:59.083 回答
2

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

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

char hname[HOST_NAME_MAX + 1];

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

您对 gethostname() 的调用:

 gethostname(hname, 255);

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

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

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

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

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

于 2013-12-27T07:41:57.350 回答
2

尽管有许多技术上正确的答案,但我认为它们实际上并没有向您解释您哪里出错了。

gethostname(char *name, size_t len);记录在这里,它基本上说参数是您分配name的字符数组,该函数将把主机名复制到其中。在这里的许多其他精彩答案中解释了你是如何做到这一点的。

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

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

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

于 2013-12-27T08:01:55.283 回答
1

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

char * fetchHostname()
{
    char* hname= malloc(sizeof(char) * 256);
    gethostname(hname, 255);

    return hname;
}

int main()
{
    char *hostname = fetchHostname();
    printf(hostname);
    free(hostname);
    return 0;
}
于 2013-12-27T07:42:12.830 回答
0
char *hname; //defined inside a function and would be destroyed after the function is executed

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

于 2013-12-27T07:48:07.920 回答