Error de violación de acceso en mi programa

Iniciado por Chains, 5 Febrero 2012, 19:48 PM

0 Miembros y 3 Visitantes están viendo este tema.

Chains

Buenos días. Estoy tratando de crear un pequeño programa cliente-servidor usando C++. He de admitir que soy un poco nuevo en esto de C++ y sobre todo en el uso de sockets (soy programador de C#).

Bien, la cuestión es que mi programa produce un error de violación de acceso (0xC0000005) al ejecutar una de sus lineas. Éste es el programa en cuestión (Es el cliente):

SOCKET client;
struct hostent * host;
char* hostname;

int main()
{
    hostname = new char[1024];
    client = socket( AF_INET, SOCK_STREAM, 0 );
    printf("Please enter the IP or name of the host to join> ");
    fflush( stdout );
    scanf("%s", hostname);
    printf("\n\nAttempting connection with host %s", hostname);
    host = gethostbyname( hostname );
    struct sockaddr_in sin;

    memset( &sin, 0, sizeof sin );

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;
    sin.sin_port = htons( 21 );
    if ( connect( client, (PSOCKADDR)&sin, sizeof sin ) == SOCKET_ERROR )
    {
    printf("Error 01: Could not connect to the defined host: %s.", hostname);
    return FALSE;
    }
    closesocket( client );
    return 0;
}


El error en cuestión me lo produce al ejecutar la siguiente línea:

sin.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;

Y no sé que hacer para solucionarlo, pues apenas hay documentación en internet acerca del uso de sockets en C++. Les agradecería que me guiaran un poco en mi tarea. Muchas gracias.

eleon

No estoy muy metido en los sockets pero me da que el fallo es más bien por la clase/estructura o por el puntero.

El error de violación de acceso se da cuando intentas acceder a una zona de memoria errónea. Si muestras las estrucutras quizá se vea más claro pero posiblemente sea o porque estás intentando acceder a una zona de la memoria (de una clase) declarada como privada sin ningún método accessor, o porque estás asignándole a un puntero el valor NULL.

Comprueba a ver y comentas. Un saludo.

Chains

#2
Pues poca cosa he podido sacar. He estado comprobando las estructuras, pero no veo nada raro.

La estructura de hostent es:

struct  hostent {
char *h_name;
char **h_aliases;
short h_addrtype;
short h_length;
char **h_addr_list;
#define h_addr h_addr_list[0]
};


Y la del in_addr:

struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;


Ambas pertenecen a la cabecera winsock2.h

Empiezo a sospechar que el error pudiera venir de antes, concretamente de ésta línea:

memset( &sin, 0, sizeof sin );

Como aloja sin en la memoria, tal vez por algún motivo el puntero se salga de la región de sin y apunte a otro lado que no debe, y de ahí el error. No estoy muy seguro.

Eternal Idol

La linea que decis solo pone ceros.

¿Que devuelve gethostbyname? Si devuelve 0 entonces es claro el motivo del fallo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Chains

#4
gethostbyname es una estructura tipo hostent . Pero he descubierto que si intento obtener el valor de h_addr de la variable host (la que contiene el valor de retorno de gethostbyname()), me da el error de violación de acceso, así que el error o está en h_addr_list, o en h_addr, o peor aún en la estructura host.

Me da error igual tanto si intento obtenerlo mediante h_addr, como por h_addr_list[0]. También he intentado definir h_addr como una variable independiente en la estructura en lugar de asignarle una región de h_addr_list, pero tampoco ha funcionado.

Eternal Idol

gethostbyname es una funcion que devuelve o un puntero a una estructura del tipo hostent o un puntero nulo, h_addr es una macro que esta definida al primer elemento de h_addr_list, asi que cambiar uno por otro es no cambiar nada. Te repito la pregunta: ¿Que devuelve gethostbyname? Dudo que sea un puntero valido ...
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Chains

Ah, de acuerdo, no sabía a lo que te referías con el valor de gethostbyname. Lo he estado comprobando y devuelve 0.

Eternal Idol

Ese es el problema, no podes acceder a host: es un puntero nulo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Chains

Entiendo. Ahora mi pregunta es, si no puedo acceder a host porque es un puntero no válido, ¿Qué tengo que hacer entonces para obtener la dirección del servidor a partir del nombre del host especificado, sin usar la estructura hostent?

Siento ser tan persistente, pero como ya he dicho, aunque tengo nociones de lo que estoy haciendo, no estoy muy experimentado en C++, y no estoy demasiado acostumbrado a todos estos temas de punteros y sockets. Intento sacar la mayor información que puedo de internet, pero no encuentro la suficiente. El código de mi programa, es sacado también de una página, y ya he tenido que resolver un sinfín de errores. No lo entiendo...

Eternal Idol

¿Que estas escribiendo en consola? ¿Estas trabajando bajo Windows? Si es asi tenes que inicializar Winsock.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón