Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I handle this pointer in getaddrinfo?

Tags:

c

sockets

Warning: Please treat me like the rookie I am. This is my first "real" C program. So if I don't understand some things, that's why.

I'm trying to make a chat server following the example from Beej's Guide to Network Programming. It came recommended, so there you go.

I want to have a function accept a pointer to a structure, modify properties in that pointer, and set up a listener on the passed port. In the below code, I am getting a Segmentation Fault, and I honestly can't figure out why. Blame me being green. (Developing in Netbeans 6.8 on Ubuntu, if needed):

#define PORT "4400"

typedef struct {
    int port;
    fd_set *connections;
    int connections_count;
    int listener;
    struct addrinfo address;
    struct addrinfo socket_hints;
} Server;

typedef struct {
    struct sockaddr_storage address;    // User's address
    int fs_id;                  // ID to the socket they belong to
    char *name;                 // Pointer to the user's name
    struct User *nextUser;      // Next user in the list
} User;

void initialize_server(Server *passed_server, char *port) {
    struct addrinfo *temp;
    int result;

    // Set up the server hints
    memset(&passed_server->socket_hints, 0, sizeof(struct addrinfo));
    passed_server->socket_hints.ai_family = AF_UNSPEC;
    passed_server->socket_hints.ai_socktype = SOCK_STREAM;
    passed_server->socket_hints.ai_flags = AI_PASSIVE;

    result = getaddrinfo(NULL, port, &passed_server->socket_hints, &temp);
    printf("Result: %d\n", result);
}

int main(int argc, char** argv) {
    // Set up socket stuff
    Server *server; // Set up the server
    memset(server, 0, sizeof(Server));

    fd_set read_sockets; // Master socket holder and sockets to read
    int new_connection; // Holds the socket ID of the new connection
    socklen_t address_length; // Used to hold the length of the address from the user
    struct addrinfo;

    // Useful sets
    char buffer[1024];
    int bytes_recieved;
    int yes = 1; // For SETOPT

    // Set up server info on defined port
    initialize_server(server, PORT);
    FD_ZERO(&read_sockets);

    return (EXIT_SUCCESS);
}

If you need the full code (I think I posted everything essential), you can find a link below. Thanks in advance for any help or attempt at it!

http://pastebin.org/529545

like image 297
Codeacula Avatar asked Aug 16 '10 03:08

Codeacula


2 Answers

The line:

Server *server;

does not actually allocate any space for a server structure, just for a pointer to one, that's set to a random value.

It looks like the change you need is:

Server *server = malloc (sizeof (Server));

which actually allocates some memory for you to use.

Think of the difference as follows:

Server *server;              |  Server *server = malloc (sizeof (Server));
       +----------+          |         +---------+     +-----------+
server | ???????? | --> ???  |  server | pointer | --> | structure |
       +----------+          |         +---------+     +-----------+
like image 53
paxdiablo Avatar answered Oct 22 '22 04:10

paxdiablo


int main(int argc, char** argv) {
// Set up socket stuff
Server *server; // Set up the server
memset(server, 0, sizeof(Server));

This is incorrect. Here, you're asking memset to zero out the memory pointed to by server. The call to memset is correct, it's the pointer server that isn't. This line:

Server *server;

Allocates memory for and gives you a pointer, but it does not allocate any memory for the pointed-to object, and it does not give the pointer an initial value. Thus, after this line, the pointer is just pointing to some random spot in memory. (It's using whatever was left over in RAM, probably) We haven't assigned it a valid value yet, so it's not valid to pass it to memset.

Now, we need to give it a valid value. You could either:

1) Allocate a Server on the stack, by just saying:

Server server;
memset(&server, 0, sizeof(server));

2) Allocate a Server dynamically, using malloc:

Server *server = malloc(sizeof(*server));
// Check for NULL, which means malloc failed.

(Also, note the use of sizeof - using the variable name instead of the type will allow the sizeof to adjust if you ever change the type of the variable.)

You might want to find and review a basic tutorial on pointers. This is a pretty classic mistake of someone who's just encounted pointers for the first time, so, don't feel too bad.

like image 24
Thanatos Avatar answered Oct 22 '22 04:10

Thanatos