[완료] 좀 재미있는(?) 가상 소멸자 질문입니다.
방금 프로그래밍 하다가 좀 재미있는(?) 것을 찾아내서 고수님들께 질문 드립니다.
.
.
.
class CTest
{
public:
CTest();
virtual ~CTest();
....(함수들 무진장)
private:
long m_lDescription;
char m_msgHeader[10];
....(멤버변수들 무진장)
};
이러한 클래스가 있습니다.
이걸 이용하여 모의 테스트 장치를 만드는데..
무진장 많은 멤버 변수들을 초기화 하는 부분을 코딩 하기가 좀 귀찮았습니다.
그래서 다음과 같은 잔꾀를 피웠습니다(죄.. 죄송합니다..ㅠ.ㅠ 돌은 던지지 말아주쎄요..;;);;
--------------------------------------------------------------------
CTest * pTest = new pTest;
memset(pTest, 0, sizeof(무진장 많은 멤버변수크기));
--------------------------------------------------------------------
아시다시피 클래스를 멤셋하면 클래스의 멤버 변수가 초기화 됩니다.
다음에 생성된 클래스는 지워야 하니까..
--------------------------------------------------------------------
delete pTest;
--------------------------------------------------------------------
..를 넣었는데요, 여기서 죽어버리더군요.. ㅡ_ㅡ);;;
다행이도 비주얼 스튜디로를 쓰는지라 디버깅을 돌려 찾아보니,
제일 첫 멤버변수인 m_lDescription앞을 알 수 없는 무언가가 자리를 차지하고 있더군요.
예상대로라면 당연히
--------------------------------------------------------------------
m_lDescription;
m_msgHeader[10];
...
--------------------------------------------------------------------
이런 순서여야 하지만..
--------------------------------------------------------------------
__vfptr
long m_lDescription;
char m_msgHeader[10];
...
--------------------------------------------------------------------
이런 순서더군요.
m_lDescription이 나오기 전에 __vfptr이라는 것이 있고..
이것이 바로 "가상 소멸자"를 선언했을때 나오는 것이라는 것과 포인터라는 것을 알아 냈습니다.
이것이 0으로 초기화가 되어 버리는 소멸자 호출이 되지 않아서 delete하면 죽어버리는 듯 싶더군요.
(1) 대체 가상 소멸자를 선언하면 나오는 __vfptr이라는 것은 어째서!! 변수로 취급되는지요?
(2) __vfptr은 주소를 가르키고 있던데.. 이 주소는 무엇인가요?
해서는 안될짓을 해버리니.. 무언가 알수 없는 것이 나와버려서.. 시간만 더 걸리게 되고, 머리가 아파옵니다만..
무언가 새로운 것을 알았다!는 재미도 발생하는 군요.
부디 알고 계시는 분은 사소한 것 일부라도 좋으니 조언좀 부탁드립니다... __);
그럼.. 즐프되십시요.
vtable
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.3
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.4
Optimization hinders evolution.
Optimization hinders evolution.
http://shurain.egloos.com
http://zooty38.egloos.com
제가 알기로 class의
제가 알기로 class의 메모리구조는 inheritance등을 위한 virtual function table, 즉 실제 해당 클래스의 오브젝트가 call하게 될 함수들의 pointer들이 들어가고, 그 다음이 member variable 등이 들어가는것으로 알고 있습니다.
따라서 memset을 해 버리는 function table의 함수주소들이 NULL이 되어버릴것이고, 따라서 위와같은 결과가 나오지 않을까 하네요...
딴 얘기입니다만
이건 제가 Linux를 잘 몰라서 여쭤보는데요, linux에서 compile된 내용, 그러니까 debug symbol과 함께 해당 assembly code가 같이 보이는 툴이 있는지요? 죄송합니다....
-------------------------------------------------
$yes 4 8 15 16 23 42
가상함수테이블
가상함수테이블 포인터라는 것입니다.
C++에선 가상함수라는게, 대강 말하자면 런타임시에 조건 분기 만들면서 테이블에서 적합한 함수를 찾아서 반환해주는 식으로 구현되어있기 때문에, 가상함수를 포함하는 클래스에는 그 테이블을 가리키기 위한 포인터가 들어갑니다.
이때문에 가상함수 호출은 느리다고 하는 거구요.
그리고 이 포인터는, 변수로 취급하는게 아니라, 실제로 메모리를 차지하고 있는 변수입니다.
그래서 아무것도 없이 가상소멸자 하나만 선언한 클래스라도 sizeof를 써보면 포인터크기(보통 4바이트)가 나옵니다.
더 자세한걸 알아보시고 싶으시면 가상함수테이블에 대해서 찾아보시면 될것 같습니다.
답변 감사드립니다.
세분 모두 답변 감사드립니다.
덕분에 얼추 이해가 됬습니다.. 좀더 찾아보고 제대로 이해를 해야겠네요.
shurain님의 링크자료가 꽤나 좋은듯(?) 싶은데.. 영어실력이 많이 딸리는 지라 절반정도밖에 이해를 못하겠네요.
xylosper님께서 말씀해주신 부분과 수도코드 정도는 이해가 되네요.
답변 감사드립니다.. ^^
댓글 달기