2010-08-16 4 views
8

Attention: S'il vous plaît traitez-moi comme la recrue que je suis. C'est mon premier "vrai" programme C. Donc, si je ne comprends pas certaines choses, c'est pourquoi. J'essaye de faire un serveur de causerie en suivant l'exemple du guide de programmation de réseau de Beej. Il est venu recommandé, alors voilà.Comment gérer ce pointeur dans getaddrinfo?

Je souhaite qu'une fonction accepte un pointeur sur une structure, modifie les propriétés de ce pointeur et configure un écouteur sur le port transmis. Dans le code ci-dessous, je reçois une erreur de segmentation, et honnêtement, je n'arrive pas à comprendre pourquoi. Blame moi d'être vert. (En développement dans Netbeans 6.8 sur Ubuntu, si nécessaire):

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

Si vous avez besoin du code complet (je pense que je posté tout l'essentiel), vous pouvez trouver un lien ci-dessous. Merci d'avance pour toute aide ou tentative!

http://pastebin.org/529545

+1

+1, pour un excellent premier article. Bienvenue à StackOverflow. La seule chose que je peux penser à cela pourrait améliorer ceci: Si vous exécutez ce code via un débogueur, disons gdb, avec des informations de débogage, il devrait vous dire sur quelle ligne ce code est segfaulting, ce qui peut être un bon point de départ. débogage. – Thanatos

+0

Merci. Je vais jeter un coup d'oeil dans cela. – Codeacula

+1

Juste quelques conseils. Vous pourriez vouloir essayer de développer sur emacs 23. Aussi quand vous obtenez un souche de pile, qui sont normalement provoqués en adressant la mémoire non valide. Essayez d'utiliser gdb et backtrace (bt). Cela vous mènera à la ligne qui a échoué. Et aussi installer valgrind son très bon pour tracer les erreurs de mémoire. c'est-à-dire valgrind --leak-check = yes ./your_app. J'espère que cela pourra aider. – ant2009

Répondre

6

La ligne:

Server *server; 

n'attribue en fait un espace pour une structure de serveur, juste pour un pointeur vers une, qui est mis à une valeur aléatoire.

Il semble que le changement que vous avez besoin est:

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

qui alloue en fait un peu de mémoire pour vous d'utiliser.

Pensez à la différence comme suit:

Server *server;    | Server *server = malloc (sizeof (Server)); 
     +----------+   |   +---------+  +-----------+ 
server | ???????? | --> ??? | server | pointer | --> | structure | 
     +----------+   |   +---------+  +-----------+ 
+0

Mais l'appel n'est-il pas suivi? memset (serveur, 0, taille de (serveur)); – Codeacula

+1

Non, c'est presque certainement celui qui cause l'erreur. Tout 'memset' est de remplir la mémoire avec une valeur donnée, vous devez toujours avoir un bloc de mémoire adressable valide - vous lui passez effectivement une adresse aléatoire pour commencer à remplir. Quand j'utilise le malloc, je récupère 'Result: 0' du programme. – paxdiablo

+0

Merci, ça l'a absolument fait! Cela m'a aidé à mieux comprendre le pointeur. – Codeacula

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

Ceci est incorrect. Ici, vous demandez memset de mettre à zéro la mémoire pointée par server. L'appel à memset est correct, c'est le pointeur server qui ne l'est pas. Cette ligne:

Server *server; 

Alloue la mémoire et vous donne un pointeur, mais il n'alloue pas de mémoire pour la pointe à l'objet, et il ne donne pas le pointeur d'une valeur initiale. Ainsi, après cette ligne, le pointeur pointe juste vers un point quelconque de la mémoire. (Il utilise probablement tout ce qui restait dans la RAM.) Nous ne lui avons pas encore attribué de valeur valide, donc il n'est pas valide de le passer à memset.

Maintenant, nous devons lui donner une valeur valide. Vous pouvez soit:

1) Allouer un Server sur la pile, en disant simplement:

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

2) Allouer un Server dynamique, en utilisant malloc:

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

(Aussi, notez la l'utilisation de sizeof - en utilisant le nom de variable au lieu du type permettra au sizeof de s'ajuster si vous changez le type de la variable.

Vous pouvez trouver et réviser un didacticiel de base sur les pointeurs. C'est une erreur assez classique de quelqu'un qui vient d'inscrire des pointeurs pour la première fois, alors, ne vous sentez pas trop mal.

+0

Très apprécié, Thanatos. En fait, j'ai juste fini d'apprendre cela à l'école, mais l'exemple était prêt. J'apprends mieux en faisant mes propres erreurs. J'ai totalement oublié malloc. J'ai eu memset sur l'esprit en regardant d'autres postes pour une réponse d'abord. Je l'avouerais si je pouvais. Merci beaucoup pour l'accueil chaleureux, aussi. – Codeacula

Questions connexes