CAsyncSocket을 이용해 통신을 하려고 하는데 vector와 string 클래스를 바로 보낼수 있나요?
글쓴이: kknd345 / 작성시간: 일, 2009/01/18 - 7:08오후
처음에 CSocket을 이용한 CArchive의 Serialize로 통신 구성을 했습니다.
그런데 이 경우 여러개의 소켓을 사용할 때 OnReceive가 무시되는 경우가 발생해서
CAsyncSocket을 이용해 통신을 하려고 하는데
CAsyncSocket은 recv를 할때 그냥 char나 byte 버퍼에다 데이터를 받아오는 방식입니다.
그렇다면
class bb
{
int a;
string b;
}
class aa
{
string name;
string id;
string tt;
vector info;
}
가 있을때
만약 제가 클래스 aa 를 통신으로 보내고 싶어
memcpy( buf, aa, sizeof(aa) );
이런식으로 버퍼에 내용을 채워서 통신으로 보낸후
유사하게 memcpy로 클래스에 바로 복사를 하여 구성하면 별 문제 없이 클래스가 보낸 상태 그대로
받은쪽 컴퓨터에서도 내용이 채워지나요?
아니면 간단한 다른 방법이 없나요?
그리고 string 클래스를 char 배열로 변환해서 안 보내도 문제 없나요?
Forums:
네트워크로 보내는
네트워크로 보내는 것에 대해서는 잘 모르겠어서 보내고 받는 부분에서 문제가 있는지는 모르겠지만, memcpy를 이용해서 객체를 복사하는 부분은 문제가 있습니다.
std::string의 경우는 성능을 위해서 implicit sharing이란 것을 통해서 구현된 경우가 있습니다. 이경우 너무 빈번한 복사를 방지하기 위해서, 데이터를 별도의 공간에 격납하고, 데이터에는 포인터로 접근하도록 되어있습니다. 그리고 대입연산자나 복사 생성자를 이용한 복사에 대해서는 포인터만 복사하고 데이터는 복사하지 않고, 실제로 데이터의 복사가 필요한 경우에만 데이터를 복사하도록 되어있습니다. 따라서 단순히 memcpy를 하면 포인터의 주소만 복사될뿐 실제 데이터는 복사되지 않습니다. 그럼에도 불구하고, 이경우에는 대입연산자나 복사생성자가 호출되지 않았기 때문에 reference count는 변하지 않습니다.
std::string *s1 = new std::string("test");
std::string s2;
memcpy(&s2, s1, sizeof(*s1));
delete s1;
int size = s2.size();
std::string이 implicit sharing을 이용해서 구현되었을 경우, 위 코드는 마지막 라인에서 런타임 에러가 발생하게 됩니다. memcpy를 통해서는 reference count가 증가하지 않기 떄문에 delete s1에서 "test"에 대한 데이터가 삭제되버리고, s2내부에서 implicit sharing을 위한 포인터는 댕글링포인터가 되버립니다.
std::vector의 경우는 implicit sharing이 없지만, 클래스는 기본적으로 내부동작을 은폐하고 있기 때문에, 복사 생성자나 대입연산자를 이용하지 않은 복사에 대해서는 안전성을 장담할 수 없습니다.
더군다나 네트워크로 전송한다면, 메모리주소란 것은 아무런 의미가 없으므로, 포인터를 포함하고 있는 클래스라면 implicit sharing을 하던 안하던 memcpy만으로는 제대로된 데이터 전송이 불가능 하겠지요.
당연히 문제가
당연히 문제가 생깁니다.
저게 문제가 없으면 세상에 serialize라는 개념은 없어도 되겠죠?
Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.
댓글 달기