2010-11-05 84 views
0

我的代碼開始:的Winsock的recv給10014錯誤

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]; 

//... 

現在,當我運行這段代碼RET變爲-1和WSAGetLastError()返回10014,這意味着指針是壞的。
但我不明白爲什麼這不應該工作?如果我將reinterpret_cast行註釋掉,並使用下面的行,它會起作用!
可能有人認爲reinterpret_cast有風險,但我認爲應該可以,因爲無符號字符和有符號字符的大小完全相同。
就我所知,std :: vectors應該是安全的,可以直接在內存中尋址。

有趣的是,當我在send()中使用相同的向量類型做同樣的事情時,它可以工作!發送功能:

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

    int ret = send(m_socket, p_buf, (int)buf.size(), 0); // Works 
} 

正如我們看到的,除了在這種情況下CharBuf是常量沒有區別,可以在改變什麼?

爲什麼recv()比send()更敏感? recv()怎麼能知道指針是無效的(它顯然不是)?它應該看到的只是一個char數組!

根據要求我的整個接收功能(請記住,我在那裏不能拼寫出每一個功能,但我認爲他們應該是相當不言自明。

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

沒關係。我發現當我嘗試爲其他人解釋它時,你會發現你的錯誤:) 我把它留給讀者來弄清楚什麼是錯誤的,但我會給& pData [0 ]作爲提示。 感謝您的幫助:D

+0

操作系統可以告訴你傳遞了一個錯誤的指針,並且可以返回EFAULT而不是簡單地殺死你的程序。發佈您正在使用的確切代碼,或最小的測試用例。你有什麼好看的。 – Thanatos 2010-11-05 16:51:55

+0

片段看起來不錯。所以......在你正在編譯的實際代碼中,你是否仔細檢查過「buf」實際上是否分配了一個緩衝區?你是否檢查過是否意外地調用了'buf.reserve()'而不是'buf.resize()'?你是否檢查過'p_buf'的值,看它在傳遞給'recv'之前是否看起來合理? – TheUndeadFish 2010-11-05 17:12:06

+0

如果你檢查整個函數,我相信你會發現我犯的錯誤,指針可以欺騙你有時:) – DaedalusAlpha 2010-11-05 17:15:40

回答

0

粘貼整個函數時自己找到答案,& pData [0]是一個提示。

+0

是的,這是問題線。對於其他人的參考,'pData'參數是一個CharBuf *指針,因此訪問'pData [0]'不會正確調用'std :: vector :: operator []'。您需要先取消引用指針,例如:char * p_buf = reinterpret_cast (&(* pData)[0]);' – 2010-11-06 01:42:52

+0

您也可以使用at()函數:char * p_buf = reinterpret_cast (& (pData->在(0)));這實際上就是我所做的。 – DaedalusAlpha 2010-11-08 08:36:12