memcpy后访问冲突:访问冲突读取位置

时间:2014-10-29 10:30:33

标签: c++ memcpy

if (m_Connections[t].socket != INVALID_SOCKET)
{
    m_TCPResult = recv(m_Connections[t].socket, m_TCPRecvbuf, m_TCPRecvbuflen, 0);

    if (m_TCPResult > 0)
    {
        printf("[TCPReceive] Bytes (m_TCPResult) received from %d: %d\n", m_Connections[t].socket, m_TCPResult);

        // Deserialize the data
        Packets::MainPacket receivedData;
        memcpy(&receivedData, m_TCPRecvbuf, sizeof(receivedData));

        // Check the type and do something with the data
        CheckType(m_Connections[t].socket, receivedData);
    }
    else  
    {
        if (WSAGetLastError() != WSAEWOULDBLOCK)
            printf("TCPReceive error: %d\n", WSAGetLastError());
    }
}

所以我有这段代码。我需要做一个memcpy()来将来自winsock的传入数据转换为可以被应用程序读取的结构。但是,在CheckType()方法完成后,应用程序崩溃,给我一个访问冲突读取位置错误。我删除了memcpy()方法一次检查然后它工作正常(没有崩溃)。

我不知道问题可能是什么。我一直在谷歌搜索,但没有发现任何有用的东西似乎是我的问题的解决方案

编辑:

更多信息:

// in the header
char m_TCPRecvbuf[DEFAULT_BUFLEN];

// receivedData struct
struct MainPacket
{
    char type;
    int id;

    LoginData loginData;
    vector<PlayerData> playerData;
};

1 个答案:

答案 0 :(得分:1)

当您执行vector时,您正在撰写memcpy。这不是POD你不能通过memcpy初始化它,而是必须使用它的成员函数来初始化它。

以这种方式思考,vector将指向它管理的数据,并且size_t至少指示大小。您不能只通过memcpy通过网络收到的值来初始化指针。指针可能对发送者有意义,但是当你收到它时,你所拥有的只是一个在服务器上有效的指针,而不是你的应用程序。因此,当您尝试使用vector时,您将获得未定义的行为,并且可能会崩溃(如果您很幸运)。

此外,由于此sizeof不适用于您应用于类时的预期方式。例如,如果您的vector中包含1,000个项目,那么sizeof将不会反映这一点。 sizeof告诉您的是类定义中所有成员变量的组合大小(取决于填充)。如果我们的vector实现只是一个指针和size_t那么它在32位平台上可能大约为8个字节,而在64位平台上则为16个,无论向量中有多少项。

您需要做的是对数据包中的信息进行编码,以便对其进行解码。例如,不是发送vector您的数据包应该包含一个字段,指示PlayerData个实例的数量,然后是每个播放器的数据。