멤버 함수 포인터의 크기

C 에서 함수포인터의 크기는 아주 예외적인 경우를 제외하고는 void* 의 크기와 같다. 즉, 모든 포인터의 크기가 CPU word 크기다 ((MS Windows 환경에 익숙한 사람들이라면 WORD 타입이랑 헷갈릴지도 모르지만, 이건 OS 관점에서의 형 문제로, 이 글에서 언급하는 word 크기는 해당 플랫폼이 생각하는 CPU 레지스터 크기다)) 하지만 멤버 함수 포인터의 경우는 조금 다른 얘기가 된다.

지지난 주에 우연히 발견하게 된 사실인데 — Visual Studio 2005의 데이터 visualization 버그인듯 함 — 멤버 함수 포인터를 저장하고, 이걸 가지고 모종의 작업을 하는 템플릿 라이브러리를 짰는데 — 2년 전에 작성해놓고 그 동안 잘 쓰던 녀석 — 이 녀석을 쓰는 코드를 디버깅하다가 생각없이 실행 스택을 따라 내려갔는데, 멤버 함수 포인터 배열에 3단위(12  bytes)로 뛰어넘으면서 접근하는게 아닌가!

실제로는 다른 부분의 코드에서도 일관성 있게 접근하고, 이걸 template 없이 짜면 별 이상없이 1 단위로 점프하는걸로 봐선(여기선 그냥 8bytes씩) 그냥 버그인듯. ((그러니까 IDE에서 데이터를 보여주는 부분의 아주 미묘한/사소한)) Visual Studio 와 관련해서는 Raymond Chen이  이걸 잘 정리해놨다 — Pointers to member functions are very strange animals. 즉, member function pointer 그 자체와, data 영역에 대한 오프셋이 들어가서 저 모양이란 소리.

GCC 에 대해서도 간단한 코드를 돌려보니 비슷한 결과가 나온다.  Mac OS X(Snow Leopard) 에서 4개의 (일반) 함수포인터를 넣은 배열의 크기 32 bytes, 멤버 함수 포인터를 4개 넣은 경우엔 64 bytes 크기로 나왔다. 즉, 각각 8 bytes 와 16 bytes. 윈도우즈의 예랑 좀 다른건 이 경우엔 64bit 으로 컴파일 했기 때문. 32  bit linux에서 동일한 파일을 컴파일해서 실행해보면 16  bytes / 32 bytes 가 나올 뿐…

 

결론:  Compiler 마다 멤버 함수 포인터 크기는 다를 수 있으며, 이 역시 플랫폼(CPU 워드 크기  /  OS / 컴파일러)에 따라 다르게 된다. 그리고 일반적으로 이 크기는 일반 함수 포인터 보다 크다. ((왜냐하면 다중 상속이나 virtual 상속 때문에…))

Jinuk Kim
Jinuk Kim

SW Engineer / gamer / bookworm / atheist / feminist

Articles: 935

8 Comments

    • 헉, 댓글 내용 중엔 처음 보는 사실도 있군. 알 수 없는 포인터면(=전방 선언 얘기겠지?) 크기가 증가한다라…

    • 저도 그 링크 따라가보고나서 “아 이거 제대로 읽었었다면…” 했어요 ㅠㅠ

      딴거 디버깅하다 말고, 저런 일이 일어나니까 왠지 궁굼해서 일은 안하고 놀아버렸(?)거든요.

  1. 오, 저 링크 따라가서 나오는거, 저도 생전 처음보는겁니다뇽. 알수없는 포인터는 크기가 크구나 … ㄷㄷㄷ

  2. 저 문제로 정말 개고생하다가 컴파일러 버그인가 싶어서 블로그에 올렸다가 조성경님의 주옥같은 한 말씀에 감동의 눈물 흘리며 문제를 찾았죠. 꽤 복잡한 프로그램을 짜고 있었는데 (C++ 클래스 범벅, 복잡한 상속구조) 원래는 잘 돌아가다가 아마 제가 헤더파일을 좀 수정했더니 제가 겪었던 그런 문제가 벌어졌더군요. 어떻게 보면 C/C++의 컴파일링 방식이 너무 원시적이다보니 벌어진 일일 수도 있겠네요.

    • 저도 저 현상을 처음봤을 땐 OS 문제인가 싶어서 리붓하고 이짓저짓다했습니다. 그러다가 별문제없길래 원인만 궁굼해했는데 , The Old New Things에서 정보를 얻고, 조성경님 댓글 보니까 문제가 확실히 풀리더라고요.

      사실 제 경우엔 문제가 된건 아니었는데(궁굼하긴 했어도), 실제로 이걸 다루는 부분이 있는 경우엔 민장님처럼 골치아픈 경우가 생길듯합니다. C++이 너무 구시대적인 컴파일 방식을 가지고 있어서인데, 이건 사실 뭔가 적당한 work-around도 못 나올듯하고 괴로운 일입니다;;;

Leave a Reply