Как мне обработать этот указатель в getaddrinfo? - PullRequest
8 голосов
/ 16 августа 2010

Предупреждение: Пожалуйста, относитесь ко мне как к новичку. Это моя первая "настоящая" программа на Си. Поэтому, если я чего-то не понимаю, вот почему.

Я пытаюсь создать чат-сервер, следуя примеру из Руководства Биджа по сетевому программированию. Пришло рекомендовано, вот и все.

Я хочу, чтобы функция принимала указатель на структуру, изменяла свойства в этом указателе и настраивала прослушиватель на переданном порту. В приведенном ниже коде я получаю ошибку сегментации и, честно говоря, не могу понять, почему. Вини меня за то, что я зеленый. (Разработка в Netbeans 6.8 в Ubuntu, если необходимо):

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

Если вам нужен полный код (я думаю, что я разместил все необходимое), вы можете найти ссылку ниже. Заранее благодарим за любую помощь или попытку!

http://pastebin.org/529545

Ответы [ 2 ]

6 голосов
/ 16 августа 2010

Строка:

Server *server;

фактически не выделяет никакого пространства для структуры сервера, только для указателя на него, для которого установлено случайное значение.

Это выглядит каквам нужно изменить:

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

, что фактически выделяет вам память для использования.

Подумайте о разнице следующим образом:

Server *server;              |  Server *server = malloc (sizeof (Server));
       +----------+          |         +---------+     +-----------+
server | ???????? | --> ???  |  server | pointer | --> | structure |
       +----------+          |         +---------+     +-----------+
2 голосов
/ 16 августа 2010
int main(int argc, char** argv) {
// Set up socket stuff
Server *server; // Set up the server
memset(server, 0, sizeof(Server));

Это неверно.Здесь вы просите memset обнулить память, на которую указывает server.Вызов memset правильный, указатель server - нет.Эта строка:

Server *server;

Выделяет память и дает указатель, но не выделяет память для объекта, на который указывает указатель, и не дает указателю начальное значение.Таким образом, после этой строки указатель просто указывает на какое-то случайное место в памяти.(Возможно, он использует то, что осталось в ОЗУ). Мы еще не присвоили ему допустимое значение, поэтому нельзя передавать его в memset.

Теперь нам нужно дать ему действительное значение.значение.Вы можете либо:

1) выделить Server в стеке, просто сказав:

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

2) выделить Server динамически, используя malloc:

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

(Также обратите внимание на использование sizeof - использование имени переменной вместо типа позволит sizeof настроить, если вы когда-либо измените тип переменной.)

Возможно, вы захотите найти и просмотреть базовый учебник по указателям.Это довольно классическая ошибка для человека, который только что включил указатели в первый раз, так что не расстраивайтесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...