Error de violación de acceso en mi programa

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

0 Miembros y 1 Visitante están viendo este tema.

Chains

Si, estoy realizando un programa de consola en Windows. Uso el entorno de desarrollo Code::Blocks, y de compilador el GNU GCC Compiler, que viene por defecto con éste entorno de desarrollo. El código, por cierto, lo saqué de ésta página: http://www.nullterminator.net/winsock.html, y sólo le realicé algunas modificaciones al código del servidor, porque me daba algunos errores y también para ajustarlo a mis necesidades.

He probado a inicializar winsock en el programa cliente usando el siguiente código:

Código (cpp) [Seleccionar]
WSADATA wsaData;
    WORD version;
    int error;

    version = MAKEWORD( 2, 0 );

    error = WSAStartup( version, &wsaData );

    /* check for error */
    if ( error != 0 )
    {
    /* error occured */
        return FALSE;
    }

    /* check for correct version */
    if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 0 )
    {
    /* incorrect WinSock version */
        printf("\n\nError 01: Incorrect WinSock Version. LOBYTE: %n . HIBYTE: %n .", (INT*)LOBYTE( wsaData.wVersion ), (INT*)HIBYTE( wsaData.wVersion ));
        WSACleanup();
        return FALSE;
    }

    client = socket( AF_INET, SOCK_STREAM, 0 );

/* Resto del progrma */


También he añadido las correspondientes líneas al final del código para cerrar el socket, pero sigo recibiendo el mísmo error al llegar a la mísma línea.



A continuación dejo el código entero del cliente con las modificaciones realizadas:

Código (cpp) [Seleccionar]
/* CLIENT */
#define __rtems__
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
//#include <pthread.h> //Es para crear POSIX threads, lo necesitaré más tarde
#include <conio.h>
#include <iostream>
#include <conio.h>
#include <fstream>

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

int main()
{
    hostname = new char[1024];
    WSADATA wsaData;
    WORD version;
    int error;

    version = MAKEWORD( 2, 0 );

    error = WSAStartup( version, &wsaData );

    /* check for error */
    if ( error != 0 )
    {
    /* error occured */
        return FALSE;
    }

    /* check for correct version */
    if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 0 )
    {
    /* incorrect WinSock version */
        printf("\n\nError 01: Incorrect WinSock Version. LOBYTE: %n . HIBYTE: %n .", (INT*)LOBYTE( wsaData.wVersion ), (INT*)HIBYTE( wsaData.wVersion ));
        WSACleanup();
        return FALSE;
    }

    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 );
    //printf("\n%p", host); //DEBUG
    struct sockaddr_in sin;

    memset( &sin, 0, sizeof sin );
    //printf("\nSuccess0"); //DEBUG
    sin.sin_family = AF_INET;
    //printf("\nSuccess1"); //DEBUG
    sin.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;
    //printf("\nSuccess2"); //DEBUG, el programa se traba aqui
    sin.sin_port = htons( 21 );
   
    if ( connect( client, (PSOCKADDR)&sin, sizeof sin ) == SOCKET_ERROR )
    {
        printf("\n\nError 01: Could not connect to the defined host: %s.", hostname);
        return FALSE;
    }
   
    WSACleanup();
    closesocket( client );
    return 0;
}

BlackZeroX

#11
Te dejo un trozo de mi clase CSocketClient, Posiblemente te sirva para solventar ese error (lineas en color resaltado):

Ademas te dejo dos PDF para saber sobre WinSock (Tuto por MazarD) y la creación de Hilos (estandares POSIX) en este enlace (http://infrangelux.sytes.net/filex/?dir=/BlackZeroX/Programacion/papers ).

Código (cpp,29,31,37,38,40,42) [Seleccionar]

bool CSockClient::connect(const char* szIP, unsigned short int iPort)
{
   hostent* lpHosten = NULL;

   if (this->iState != SCKCLOSED )
   {
       this->setError();
       return false;
   }

   if (szIP == NULL || iPort == 0)
       return false;

   this->iRemotePort = iPort;
   this->sRemoteHost = szIP;

   memset(&this->udtSockAddrIn, 0, sizeof(sockaddr_in));

   this->udtSockAddrIn.sin_family = AF_INET;
   this->udtSockAddrIn.sin_port = htons(iPort);
   this->iState = SCKOPEN;

   if (this->udtSockAddrIn.sin_port == INVALID_SOCKET)
   {
       this->setError();
       return false;
   }

   lpHosten = ::gethostbyname(this->sRemoteHost.c_str());

   if (lpHosten == NULL)
   {
       this->setError();
       return false;
   }

   this->udtSockAddrIn.sin_addr.s_addr = *((unsigned long*)lpHosten->h_addr_list[0]);
   // memcpy(&uiRet, hHost->h_addr_list[0], hHost->h_length);

   this->sLocalHostIP.assign(inet_ntoa(this->udtSockAddrIn.sin_addr));

   if (this->udtSockAddrIn.sin_addr.s_addr == INADDR_NONE)
   {
       this->setError();
       return false;
   }

   this->mySock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

   if (this->mySock == INVALID_SOCKET)
   {
       this->setError();
       return false;
   }

   if (!this->getSocketOpt())
       return false;

   //Creamos el hilo para resivir los datos de este Socket.
   if (pthread_create(&this->threadConnect, NULL, myCallConnect, this))
   {
       if (this->pEventError != NULL)   //Evento
           this->pEventError(this);

       if (this->mySock != INVALID_SOCKET )
           closesocket(this->mySock);

       this->mySock = INVALID_SOCKET;

       this->setError();

       return false;
   }
   pthread_detach(this->threadConnect);   //  No guardar Returns del hilo...

   return true;
}


Timibles Lunas!¡.
The Dark Shadow is my passion.

Chains

Muchísimas gracias por tu aporte, BlackZeroX. Sinceramente, me es de gran ayuda. Pero hay una cosa que no me explico.

He logrado pasar de la linea erronea, pero ahora el error me lo produce en la función "connect".

Código (cpp) [Seleccionar]
connect(sock, (SOCKADDR *)&remoto, sizeof (remoto));

Pero lo mejor, es que he descubierto, que la línea que antes no me funcionaba, en éste programa me deja de funcionar si declaro "hostent * direc" fuera de la función main.

Es decir, que si hago ésto

Código (cpp) [Seleccionar]
int main()
{
    hostname = new char[1024];
    hostent * direc = NULL;
/* ... */
    remoto.sin_addr = *((struct in_addr *)direc->h_addr);
/* ... */
}


El programa no me devuelve error en esa línea. Pero si hago ésto

Código (cpp) [Seleccionar]

hostent * direc = NULL;

int main()
{
    hostname = new char[1024];
/* ... */
    remoto.sin_addr = *((struct in_addr *)direc->h_addr);
/* ... */
}


Al llegar a esa línea, da error de violación de acceso. Ésto es algo que no logro comprender, y que tiene algo que ver seguro con la gestión de la memoria, pero no sé si es error mio, del compilador, del ordenador... no logro entender nada y mi cabeza hecha chíspas.

He probado a meter el programa en Dev-C++, pero me da error en todas las funciones de la librería winsock (aunque no me da error al importarla en la cabecera). No sé si es que tal vez debería añadir algún parametro especial en las opciones del enlazador. Lo mísmo pasa si en Code::Blocks cambio el compilador al LCC, que me lo bajé para probar a ver si funcionaba bien así, sólo que en éste caso me da error en todas las líneas. Es un verdadero caos.

BlackZeroX

realiza un linkeo a esta libreria (CodeBlock):

MinGW\lib\libws2_32.a

Dulces Lunas!¡.
The Dark Shadow is my passion.

Eternal Idol

Ya estas mezclando codigos de diferentes fuentes y haciendo copy/paste sin entender, es el problema de dejar codigo compulsivamente en el foro ante cada duda. El ultimo codigo que habias dejado deberia funcionar (comentando la inclusion de windows.h va perfecto con VC++), dale las vueltas necesarias (no te olvides de depurar) hasta lograrlo.
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