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() 方法进行检查,然后它工作正常(没有崩溃)。
我不知道可能是什么问题。我一直在 Google 上搜索,但没有找到任何有用的东西似乎可以解决我的问题
编辑:
更多信息:
// in the header
char m_TCPRecvbuf[DEFAULT_BUFLEN];
// receivedData struct
struct MainPacket
{
char type;
int id;
LoginData loginData;
vector<PlayerData> playerData;
};
最佳答案
当您执行 memcpy
时,您正在覆盖 vector
。这不是 POD你不能通过 memcpy
初始化它,而是必须使用它的成员函数来初始化它。
这样想,vector
将至少有一个指向它管理的数据的指针和一个指示大小的 size_t
。您不能仅通过 memcpy
ing 您通过网络收到的值来初始化指针。指针对发送者来说可能有意义,但是当你收到它时,你得到的只是一个在服务器上有效的指针,而不是在你的应用程序中。因此,当您尝试使用 vector
时,您将获得未定义的行为并且可能会崩溃(如果幸运的话)。
此外,由于此 sizeof
无法以您期望的方式应用于类。例如,如果您的 vector
中有 1,000 个项目,那么 sizeof
将不会反射(reflect)这一点。 sizeof
告诉您的是类定义中所有成员变量的组合大小(受填充)。如果我们的 vector
实现只是一个指针和一个 size_t
那么它在 32 位平台上可能大约是 8 个字节,在 64 位平台上大约是 16 个字节,无论有多少项在 vector 中。
您需要做的是对数据包中的信息进行编码,以便您可以对其进行解码。例如,您的数据包不应发送 vector
,而是应包含一个字段,指示 PlayerData
实例的数量,后跟每个玩家的数据。
关于c++ - memcpy : access violation reading location 后崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26628007/