Question

The following C program attempts to fetch and print the host name of the current RHEL host. It throws a segmentation fault on this machine. As per the definition of gethostname I should be able to pass a char pointer, shouldn't I?

When I use a char array instead (like char hname[255]), the call to gethostname works. (If I did this how would I return the array to 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;
}

Output:

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 >
Was it helpful?

Solution

As gethostname man said:

The gethostname() function shall return the standard host name for the current machine. The namelen argument shall specify the size of the array pointed to by the name argument. The returned name shall be null-terminated, except that if namelen is an insufficient length to hold the host name, then the returned name shall be truncated and it is unspecified whether the returned name is null-terminated.

You need a place to store the function information, so declare hostname as an array, not a pointer.

#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;
}

OTHER TIPS

When I use a char array instead (like char hname[255]), the call to gethostname works. (If I did this how would I return the array to main?)

By passing a pointer to the array from main() to your function. Note that this approach makes your function fetchHostname() to be just a wrapper for function gethostname():

#include <stdio.h>
#include <unistd.h>
void fetchHostname(char *hname)
{
    gethostname(hname,255);
}

int main()
{
    char hostname[256];

    fetchHostname(hostname);
    return 0;
}

Or by declaring your hname[] array local static, so it is valid even after the program leaves the function (this approach is not thread-safe):

#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;
}

Though there are many technically correct answers I don't think that they actually explain to you where you went wrong.

gethostname(char *name, size_t len); is documented here and it basically says that the parameter name is an array of characters that you have allocated where this function will copy the hostname into. And how you do that is explained in the many other wonderful answers here.

That is why this works if you make the array yourself but causes a segmentation fault if you just give it a pointer.

Also, you were giving this function an uninitialized pointer so when it tried to copy data to that address (which is just some completely random place in memory) it caused your program to terminate because it was trying to write a string where it isn't allowed to.

This type of mistake tells me that you need to brush up on what pointers actually are and that you need to understand that they can be used to allow a function to return a value in a different way than using the return statement.

Update: please see @Tio Pepe's answer.

You need to allocate space in your array (either statically or dynamically):

char hname[HOST_NAME_MAX + 1];

otherwise you are passing an uninitialised pointer that could point anywhere.

Your call to gethostname():

 gethostname(hname, 255);

is a contract that says here is a pointer that points to at least 255 characters of allocated space.

Also, you are trying to return a pointer to space allocated on the stack. That's not good.

Yoi need to dynamically allocate the character array if you want to return it.

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

But be aware that you now have to manage when that space gets freed.

Returning a pointer to a local variable is undefined behavior, because it will go out of scope. If you allocate it on the heap (via dynamic allocation), you will not have this problem.

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

    return hname;
}

int main()
{
    char *hostname = fetchHostname();
    printf(hostname);
    free(hostname);
    return 0;
}
char *hname; //defined inside a function and would be destroyed after the function is executed

After the execution of fetchHostname() the address returned to the hostname is not valid and acessing it would result in segmentation fault

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top