pragma pack()실수 찾기 – pragma pack(show)

오늘의 개삽질.

VOXEL HORIZON프로젝트의 UWP버전을 빌드하던중 다음의 에러를 마주쳤다.

error C3621: ‘Windows::Foundation::EventHandler<Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs ^>::__abi_IDelegate’: only the default packing value (16) is allowed for WinRT types

에러 내용을 액면 그대로 해석하자면 WinRT타입 개체들(ref class)는 기본 팩킹 사이즈가 16bytes만 허용된다고. 처음엔 되게 황당했다. 이게 뭔 소리여? struct align이라고 표시해줬으면 좀더 빨리 눈치챘을텐데.

하여간 WinRT타입 개체들은 struct align이 x64일 경우 16bytes, x86일 경우 8bytes여야 한다는 얘기다. 나는 컴파일러의 struct align설정을 건드리지 않고 디폴트 그대로 두고 있으므로 컴파일 할 당시의 기본 상태는 x86일때 8bytes, x64일때 16bytes가 맞다. 이 에러가 발생할 수 없다.
즉 이 에러가 발생했다고 하는 것은 코드 어딘가에서 pragma pack()지시어를 잘못 사용했다는 뜻이 된다. 어딘가에서 pragma pack(push,n)한 다음에 pragma pack(pop)을 빼먹었겠지.

pragma pack()이 꽤 많은데 그 중에서 어느 녀석이 문제가 되는지 어떻게 찾는다? push / pop 짝이 맞는지 다 확인해야되는데.

다행히도 컴파일러에서 현재 struct align상태를 아웃풋 윈도우에 출력해주는 지시어가 있다.

pragma pack(show) 다. 이걸로 실수한 코드를 찾았다.

  1. 일단 프로젝트 전체에서 pragma pack()을 호출하는 코드를 몽땅 찾아냈다. cpp파일은 없고 h파일만 몇개 나온다.
  2. 그 h파일들의 맨 끝에 pragma pack(show)를 추가했다.
  3. 이제 빌드 아웃풋 윈도우에 warning C4810: value of pragma pack(show) == 16 라는 식으로 줄줄이 표시가 된다. 여기서 16이 아닌 경우를 찾는다. x64빌드에서 pragma pack()을 실수하지 않았다면 항상 16이 나와야 한다.
  4. C:\DEV\DAIKON_ROOT\VOXEL_HOIRIZON\MegayuchiDBAccess\typedef_dbaccess.h(138,9): warning C4810: value of pragma pack(show) == 1 로 표시되는 라인이 있다. 이하로는 몽땅 1 bytes align인걸로 나온다. 이 파일에서 pragma pack()을 잘못 사용했구만.
  5. 해당 h파일을 살펴보니 맨 아래 pragma pack(pop)부분을 잘못 써넣었다. 멍청하게도 pragma pack(pop,1)로 써놓고 있다. 아 이런건 컴파일러가 경고라도 띄워주면 안되냐…물론 내 잘못이긴 하지만.
  6. pragma pack(pop)으로 고치고 나니 최초의 에러도 사라졌다.

이 코드의 최초 코드가 작성한 데스크탑 프로젝트를 뒤져보니 거기도 pragma pack(pop,1)로 적어놨네.. 으아..뭐 도는덴 큰 문제는 없지. 그래봐야 exe하나고 대부분의 코드는 dll로 빠져있으니까. 하여간 잠재적 버그 하나 잡았다.


답글 남기기

댓글을 게시하려면 다음의 방법 중 하나를 사용하여 로그인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중