2014-10-29 4 views
0
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()); 
    } 
} 

그래서이 코드가 있습니다. 들어오는 데이터를 winsock에서 응용 프로그램이 읽을 수있는 구조체로 변환하려면 memcpy()를 수행해야합니다. 그러나 CheckType() 메서드가 완료되면 응용 프로그램이 충돌하여 위치 정보 액세스 위반 오류가 표시됩니다. memcpy() 메서드를 한 번 제거하고 잘 작동합니다 (충돌 없음).memcpy : 액세스 위반 읽기 위치 이후의 충돌

나는이 문제가 무엇인지 모릅니다. 나는 Google에서 검색 한 적이 있지만 내 문제에 대한 해결책이 될 것으로 보인다 유용한 아무것도 발견하지 않았습니다

편집 :

일부 추가 정보를 원하시면 :

// in the header 
char m_TCPRecvbuf[DEFAULT_BUFLEN]; 

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

    LoginData loginData; 
    vector<PlayerData> playerData; 
}; 
+0

답변이 "헤더 파일에서"인 경우 어떻게 정의됩니까? memcpy가 알려지지 않은 데이터 구조에 의심스러워 보인다. – gnasher729

+0

그리고'CheckType'에는 무엇이 들어 있습니까? – molbdnilo

+0

더 많은 데이터로 주 질문을 편집했습니다. – Dries

답변

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 인스턴스의 수를 나타내는 필드와 각 플레이어의 데이터가 있어야합니다.

+0

가능한 PlayerData의 데이터는 여전히 벡터에 있습니까? – Dries

+0

@Dries - 데이터를'vector'에 저장할 수 있습니다. 단지'memcpy' 할 수 없습니다. 데이터를 초기화하기 위해 선택하고 사용하는 약간 더 자세한 네트워크 패킷 구조가 필요합니다. 당신이 할 수없는 것은 단지 네트워크를 통해'MainPacket '을 구성하는 바이트들을 보내고 그들이 수신기에서 의미를 갖기를 기대합니다. – Sean

+0

좋아, 알았어. 당신이 말한 것처럼 여러 개의 playerData 객체를 가진 새로운 필드를 추가 할 것입니다. 그런 다음 for 루프를 수행하고 새 벡터를 채우겠습니까? 나는 그것이 내가 얼마나 많은 물체를 가지고 있고 얼마나 많은 물체를 가지고있는 한 작동해야한다고 생각하니? – Dries