son redes que protocolos protocolo modelo los internet cuáles comunicaciones comunicacion capas administración c segmentation-fault

redes - que es el protocolo tcp



Falla de segmentación en la comunicación TCP (6)

Recibo un error de segmentación en el siguiente código C:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 6667 #define MAXDATASIZE 1024 int bot_connect(char *hostname); int bot_connect(char *hostname) { int sockfd, numbytes, s; char buf[MAXDATASIZE]; struct addrinfo hints, *servinfo, *p; int rv; char m[1024]; char *message; char *nick = "Goo"; char *ident = "Goo"; char *realname = "Goo"; memset(&hints,0,sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; rv = getaddrinfo(hostname, PORT, &hints, &servinfo); if (rv != 0) { fprintf(stderr, "getaddrinfo: %s/n", gai_strerror(rv)); return 1; } for (p = servinfo; p != NULL; p = p->ai_next) { sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd == -1) { perror("Client: socket"); continue; } if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("Client: connect"); continue; } break; } if (p == NULL) { fprintf(stderr, "Client: failed to connect /n"); return 2; } freeaddrinfo(servinfo); strcat(m, "NICK "); strcat(m, nick); message = m; s = send(sockfd, message, strlen(message), 0); strcat(m, "USER "); strcat(m, ident); strcat(m, " * * :"); strcat(m, realname); message = m; s = send(sockfd, message, strlen(message), 0); message = "JOIN #C&T"; s = send(sockfd, message, strlen(message), 0); close(sockfd); }

Sé que tienes fallas de segmentación al tratar de hacer algo con memoria que no tienes permitido hacer, como alterar la memoria de solo lectura, pero que yo sepa, este programa no hace eso. ¿Alguien tiene alguna pista de dónde viene la falla de segmentación?


Aquí ya están las respuestas correctas al por qué y qué. Para responder a su "donde falla la segmentación ..." Recomiendo un depurador. Compila tu programa con información de depuración, y verás dónde sucede (simplemente déjalo correr y observa el seguimiento de la pila cuando se cuelga). La respuesta probablemente también responda el por qué y el qué (que en este caso ya está respondido)


Suba el nivel de advertencia en su compilador:

rv = getaddrinfo(hostname, PORT, &hints, &servinfo);

El segundo parámetro para getaddrinfo es un const char * , no un int. Cambie PORT a NULL y modifique el número de puerto en la estructura addrinfo antes de la connect .


Use valgrind . Valgrind es extremadamente bueno en la búsqueda de fugas de recursos y otros errores humanos comunes de mal comportamiento en su código.


Usted está llamando a strcat( m, "NICK" ); antes de que hayas inicializado m. antes del strcat, intente m[0] = ''/0''; o memset( m, 0, sizeof( m ) ); , o cambie el primer strcat a strcpy

Además, después de enviar la línea NICK al socket, llama a strcat nuevamente, que agregará la línea USER a la línea NICK. Nuevamente, probablemente strcat cambiar el primer strcat a strcpy


La matriz m contiene basura antes de su uso. Lo siguiente funcionaría:

strcpy(m, "NICK "); strcat(m, nick); message = m; s = send(sockfd, message, strlen(message), 0); strcpy(m, "USER "); strcat(m, ident); strcat(m, " * * :"); strcat(m, realname); message = m; s = send(sockfd, message, strlen(message), 0);

También lo siguiente funcionaría:

sprintf(m, "NICK %s", nick); message = m; s = send(sockfd, message, strlen(message), 0); sprintf(m, "USER %s * * :%s", ident, realname); s = send(sockfd, message, strlen(message), 0);


Graeme está correcto con el "qué" , así que aquí está el "por qué" en caso de que no estés familiarizado. En C, una cadena se define como una serie de caracteres terminados por un carácter nulo ''/ 0''. La razón por la cual una cadena tiene un carácter de terminación es para que el código pueda descubrir dónde la cadena termina lógicamente. Incluso si declaras una cadena como esta:

char m[1024];

En C no hay forma de que el código proporcionado m pueda deducir que tiene 1024 bytes asignados, y mucho menos averiguar cuántos de esos bytes son significativos, sin tener un carácter nulo que demarca el final de los bytes significativos.

strcat es una función que funciona en dos cadenas C, por lo que espera que ambos argumentos se ajusten a la especificación de que hay un byte nulo que marca el final de una entrada significativa. Si m no está inicializado, su contenido es aleatorio, por lo que el byte nulo podría estar en cualquier parte, o no podría haber ningún byte nulo. Para concatenar, strcat verá los caracteres del primer argumento tratando de encontrar el byte nulo que marca el final de la cadena. Si, por casualidad, no existe un byte nulo en la matriz no inicializada, continuará felizmente mirando más allá del final de la cadena, en ubicaciones de memoria arbitrarias que pueden corresponder a otras variables, o información de pila interna, etc.

Cuando strcat finalmente encuentre un byte nulo, escribirá felizmente los contenidos del segundo argumento comenzando en esa ubicación, y si esa ubicación está más allá del final de m, sobrescribirá alguna otra variable u otra información. Si es una dirección de memoria asignada a alguna otra variable, el problema puede ser silencioso y muy difícil de encontrar. Afortunadamente, en su caso, era una ubicación en la que no debería escribirse, por lo que su programa se bloqueó en un error obvio.

Esto también trae a colación la nota de que realmente deberías estar usando strncat en lugar de strcat. strncat te permite especificar la longitud máxima de la cadena para crear. Anoté antes que strcat no puede determinar que m tiene 1024 bytes asignados, por lo que si intentas concatenar m con algo que podría hacer m más de 1023 caracteres, terminas con el mismo problema de sobreescritura de memoria. strncat toma un tercer argumento que especifica la longitud máxima de la cadena resultante y tiene un código de retorno que indicará si la concatenación se truncó debido a que alcanzó esta longitud.