뭉근 : 느긋하게 타는 불

이번 포스트의 시작과 함께…

이런 경우는 도대체 언제 발생하는가 생각이 든다…

왜 8바이트를 컴파일러에서는 이런 식으로 처리하게 되었는가? 부터 시작해서

VC 컴파일러는 믿을만 한가? 라는 생각도 들게하는 문제이다.

일단 문제는 잘 사용되던 코드에서 갑자기 에러가 나면서 시작됐다.

에러가 난 코드는 다음 그림과 같다.

VC를 조금이라도 다뤄본 사람은 0xCC로 채워진 메모리는 초기화되지 않은 영역을 의미한다는 것을 알것이다. 근데 나는 분명히 0으로 초기화를 했으며… 8바이트 중 4바이트만 일부러 0xcc를 채우지도 않았다.

아래는 위 상태의 this 메모리 영역이다. (m_nDTB를 채우기전)

 

첫 4바이트는 vftable을 나타낸다. 문제는 그 뒤 메모리를 어떻게 사용하느냐인데… 아래를 디스어셈블 내용을 보면 알 수 있다.

 

디스어셈블을 보면 전달 인자인 _nDTB를 스택에 하위 4바이트를 넣고 edx에 상위 4바이트를 전달하여 처리한다. 처리할 때 메모리 영역을 보면 this + 0x08 부터 4바이트, 4바이트 단위로 8바이트 변수인 m_nDTB 변수에 채워넣는 것을 볼 수 있다. edx는 당연히 0이다.

이쯤 되면 코드에는 아무 문제가 없어보인다. 그런데 다시 맨 위 m_nDTB 값을 보면 이상하다는 것을 느낄 수 있을 것이다. 위 코드로 볼 때 m_nDTB가 메모리 상에서는 0으로 채워져있다는 것을… 하지만 실제 m_nDTB 값은 아래와 같이 값을 채운 후에도 이상하다는 것을…

 

위 그림은 Address 부분에  &m_nDTB를 입력했을 때 나온 결과이다. 즉, 실제 8 바이트 m_nDTB 변수 사용은 this + 0x04 인 영역부터 8바이트인 것이다. 왜 이런 상황이 발생했을까?

  1. 단순히 디버깅 정보 표시 잘못이다. m_nDTB는 0x0000000000185000으로 사용된다.
  2. 컴파일 시 무언가 잘못되었다.

1번인지 알고 release 모드로 실행했지만 m_nDTB가 쓰레기 값으로 사용되는 것을 확인하였다. 그럼 2번인데… 컴파일러가 왜 이걸 햇갈렸을까 아무리 생각해봤자 답이 안나오니…

컴파일러야 햇갈리지마 T^T 라는 생각으로 메모리 정렬 단위를 명시해주었다.

#pragma pack(4)

적어주니 아래와 같이 값이 컴파일러는 잘 판단해주었다. ㅡㅡ...

 

32비트 컴파일 시 기본 컴파일 단위가 4바이트라고 알고 있는데… 무엇이 잘못되었을까….

결론 : VC 2010 버전에서는 메모리 정렬 단위 선언으로 컴파일러에 확실히 명시해주자

   

'디버깅' 카테고리의 다른 글

MS 심볼 구성에 관하여  (0) 2014.12.17
Windows 10 _KPCR and _KPRCB  (0) 2014.11.14
Windbg에서 KDBG 찾기  (0) 2014.06.19
Window8 Remote Kernel Debugging on Vmware using WinDbg  (0) 2014.04.11
_DRIVER_OBJECT.DriverSection 정보  (0) 2013.10.05