• Virtual Table (가상함수 테이블)

    2014. 12. 18.

    by. xxx123

     

    1. 동적바인딩의 실체.

     

    우리는 일반 함수 호출은 이미 컴파일타임에 호출해야할 함수의 주소를 알기 때문에 정적 바인딩이라 하고, 가상함수 호출의 경우 런타임에 호출할 함수의 주소를 알기 때문에 동적 바인딩이라 한다.

     

    일단 헷갈리지 말아야할 것은 "가상함수 테이블"은 각 클래스 마다 가지고 있는것이지, 각 객체마다 가지고 있는것이 아니다. 각 객체가 가지고 있는것은 "가상함수 테이블 포인터"이다. 또한 가상함수 테이블은 각 클래스가 호출해야 할 함수의 주소 정보가 이미 정해져서 박혀 있다. 

     

    다음 코드를 보자.

     

     

    그리고 다음은 위의 코드를  decompile한 코드이다.

     

    7~16번째 줄 까지가 A* a = new A(); 의 부분이다.

    v-pointer + 4바이트 변수 2개를 포함해 총 12(0XCu) byte의 공간을 할당하였고, 첫번째 4byte 공간에 vftable의 주소를 넣는것을 볼 수 있다. 즉, 가상함수를 갖는 객체의 첫 4byte는 vftable의 주소라는 뜻이며 컴파일 타임에 이미 가져야할 vftable이 결정 난다는 것이다.

     

    그 다음 줄이 fct1()을 호출하는 부분인데, 어셈코드로 보자면 다음과 같다.

     

     

    결론적으로는 객체의 시작 주소값(vftalbe) -> vtable + 0 -> fuct1() 이런식의 흐름이 되는것이다.

     

    위에서 컴파일타임에 가져야할 vftable이 결정 난다고 했는데, 그럼 동적바인딩이 실제로 아니란 말인가?

    헷갈릴 수 있지만 다음 코드를 보자.

     

    다음은 위 코드의 어셈블리 코드이다.

     

    일단 봐야할 부분은 VC++ 컴파일러는 this포인터를 레지스터 ecx를 통해 얻는데, 그렇기 떄문에 함수 call 명령앞에 ecx값이 객체 b로 셋팅되는 것을 볼 수있다.

    그 다음 줄의 Func1()의 호출에 비해 Func2()는 edx + 4 만큼 더 연산을 한 위치의 함수를 호출하는것을 볼 수 있는데,

    이것은 호출할 함수의 대상이 컴파일 시간에 정해지지 않고 실행시간에 계산을 통해 결정되는 간접 분기문이란 뜻이다.

     

    정리를 하자면, 각 객체가 가지게될 vftable은 컴파일 타임에 결정나지만,

    호출해야 할 함수는 런타임에 결정난다는 뜻.

     

     

    간접분기문이기 때문에 당연히 성능에 영향을 미칠 수 있다는 부분도 알아두도록 하자.

     

     

     

     

     

     

     

    'Programming > C/C++' 카테고리의 다른 글

    전역(global)변수와 정적(static)변수  (4) 2015.06.24
    inline  (0) 2014.12.17
    CreateThread & _beginthreadex  (0) 2014.11.02
    new operator, operator new, placement new  (0) 2014.07.18
    shared_ptr  (0) 2014.06.20

    댓글