2010-11-05 5 views
0

Je vais commencer par le code:Winsock recv donne 10014 erreur

typedef std::vector<unsigned char> CharBuf; 
static const int RCV_BUF_SIZE = 1024; 
SOCKET m_socket = a connected and working socket; 

// ... 

CharBuf buf; // Declare buffer 
buf.resize(RCV_BUF_SIZE); // resize buffer to 1024 
char* p_buf = reinterpret_cast<char*>(&buf[0]); // change from unsigned char to char 
//char p_buf[RCV_BUF_SIZE]; 

int ret = recv(m_socket, p_buf, RCV_BUF_SIZE, 0); // Does not work 

for (int i=0; i<RCV_BUF_SIZE; ++i) // Works (does not crash, so the buffer is ok) 
    char c = p_buf[i]; 

//... 

Maintenant, quand je lance ce code ret devient -1 et retourne WSAGetLastError() 10014 qui signifie que le pointeur est mauvais.
Cependant, je ne vois pas pourquoi cela ne devrait pas fonctionner? Si je commente la ligne reinterpret_cast et utilise la ligne ci-dessous cela fonctionne!
On pourrait argumenter que reinterpret_cast est risqué, mais je pense que cela devrait être correct car les caractères non signés et char signés ont exactement la même taille.
std :: les vecteurs devraient être sûrs d'adresser directement dans la mémoire aussi loin que je sais aussi bien. La partie amusante est que quand je fais la même chose avec le même type de vecteur dans send() cela fonctionne! Comme nous le voyons, aucune différence à part que CharBuf étant const dans ce cas, cela peut-il changer quelque chose?

Pourquoi recv() est-il plus sensible que send()? Comment recv() peut même savoir que le pointeur est invalide (ce qui n'est évidemment pas le cas) ?? tout ce qu'il devrait voir est un tableau char!

Comme par demande toute ma fonction de réception (gardez à l'esprit que je ne peux pas préciser toutes les fonctions en elle, mais je pense qu'ils devraient être assez explicites.

bool TcpSocket::ReceiveData(CharBuf* pData) 
{ 
    if (!CheckInitialized("ReceiveData")) 
     return false; 


    if (m_status != CONNECTED_STAT) 
    { 
     AddToErrLog("Socket not connected", 1, "ReceiveData"); 
     return false; 
    } 

    int ret; 
    pData->resize(RCV_BUF_SIZE); 
    char* p_buf = reinterpret_cast<char*>(&pData[0]); 

    ret = recv(m_socket, p_buf, RCV_BUF_SIZE, 0); 

    switch (ret) 
    { 
    case 0: // Gracefully closed 
     AddToLog("Connection gracefully closed", 2); 
     Shutdown(); // The connection is closed, no idea to keep running 

     return true; 

    case SOCKET_ERROR: // Error 
     ret = WSAGetLastError(); 
     if (ret == 10004) // This indicates the socket was closed while we were waiting 
      AddToLog("Socket was shut down while waiting for data", 1, "ReceiveData(1)"); 
     else 
      AddToErrLog("Receive data failed with code: " + CStr(ret)); 

     AddToLog("Connection ended with error", 2); 

     Shutdown(); 
     return false; 

    default: // Normal operation 
     pData->resize(ret); // Remove unused space 

     return true; 
    } 
} 

Peu importe. J'ai trouvé Comme toujours, vous trouvez votre erreur lorsque vous essayez de l'expliquer à quelqu'un d'autre :) Je laisse le lecteur savoir ce qui n'allait pas, mais je vais donner & pData [0 ] comme un indice. Merci pour votre aide: D

+0

L'OS peut dire que vous lui passez un mauvais pointeur, et peut renvoyer EFAULT au lieu de simplement tuer votre programme. Postez le code exact que vous utilisez ou un cas de test minimal. Ce que vous avez l'air OK. – Thanatos

+0

Les extraits ont l'air OK. Alors ... Dans le code que vous compilez, avez-vous revérifié que 'buf' a effectivement un buffer alloué? Avez-vous vérifié si vous appelez accidentellement 'buf.reserve()' au lieu de 'buf.resize()'? Avez-vous vérifié la valeur de 'p_buf' pour voir si elle semble raisonnable avant d'être passée à' recv'? – TheUndeadFish

+0

Si vous vérifiez toute la fonction, je suis sûr que vous allez repérer où j'ai fait l'erreur, les pointeurs peuvent vous tromper parfois :) – DaedalusAlpha

Répondre

0

J'ai trouvé la réponse moi-même en collant toute la fonction, & pData [0] est un indice.

+0

Yup, c'est la ligne de problème. Pour la référence d'autres personnes, le paramètre 'pData' est un pointeur CharBuf *, donc l'accès' pData [0] 'n'invoque pas correctement' std :: vector :: operator [] '. Vous devez d'abord déréférencer le pointeur, par exemple: 'char * p_buf = reinterpret_cast (& (* pData) [0]);' –

+0

Vous pouvez également utiliser la fonction at() comme: char * p_buf = reinterpret_cast (& (pData-> at (0))); ce qui est en fait ce que j'ai fait. – DaedalusAlpha