Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)

windbg - SOS DumpClass/DumpMT의 "Vtable Slots", "Total Method Slots", "Slots in VTable" 값에 대한 의미

windbg에서 System.String 타입에 대해 DumpClass 명령을 수행해 보겠습니다.

0:000> !DumpClass 00007ff961df50e0
Class Name:      System.String
mdToken:         0000000002000073
File:            C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Parent Class:    00007ff961df5188
Module:          00007ff961df1000
Method Table:    00007ff9624f6948
Vtable Slots:    1b
Total Method Slots:  1d
Class Attributes:    102101  
Transparency:        Transparent
NumInstanceFields:   2
NumStaticFields:     1
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ff9624f9288  400026f        8         System.Int32  1 instance           m_stringLength
00007ff9624f7b00  4000270        c          System.Char  1 instance           m_firstChar
00007ff9624f6948  4000274       90        System.String  0   shared           static Empty
                                 >> Domain:Value  000002c18d980b20:NotInit  <<

위와 같이 "Vtable Slots"와 "Total Method Slots" 값이 나옵니다. "Vtable"이라는 단어로 봐서 분명 가상 메서드와 관련이 있을 것 같은데,

C++의 가상 함수 테이블 (vtable)은 언제 생성될까요?
; https://www.sysnet.pe.kr/2/0/11167

C++ 클래스 상속 관계의 vtable 생성 과정
; https://www.sysnet.pe.kr/2/0/11168

2개로 나누어져 있는 이유를 모르겠습니다. 게다가 DumpMT로 System.String 타입의 메서드 테이블을 살펴보면,

0:000> !DumpMT 00007ff9624f6948
EEClass:         00007ff961df50e0
Module:          00007ff961df1000
Name:            System.String
mdToken:         0000000002000073
File:            C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
BaseSize:        0x18
ComponentSize:   0x2
Slots in VTable: 194
Number of IFaces in IFaceMap: 7

"Slots in VTable"이란 값도 나옵니다. 이렇게 3가지로 나누어져 있다 보니 더욱 혼란스럽습니다. ^^;

이 중에서 "Slots in VTable"은 "!DumpMT -md <addr>" 명령을 내리면 그 의미를 확실히 알 수 있습니다. 왜냐하면 실제로 194개의 메서드 목록이 나오기 때문입니다. 그럼 한 가지는 정리되었군요. ^^ "Slots in VTable" 값이야말로 해당 타입이 (상속을 포함해) 소유하고 있는 전체 메서드의 수를 가리킵니다.

남은 것은 "Vtable Slots"와 "Total Method Slots"의 의미인데요. 이게 좀 재미있습니다. ^^




참고로 검색해 보면 다음과 같은 질문 글이 나옵니다.

SOS and DumpClass
; https://social.msdn.microsoft.com/Forums/vstudio/en-US/13839da8-bc06-4443-9a1b-5e326e386ff8/sos-and-dumpclass?forum=clr

정리하면, 너무 난이도가 있는 질문이라 더 진행하려면 "유료" 기술 지원을 신청해야 한다는 답변이 나옵니다. 그래서 저도 그냥 접을까 하다가 호기심이 생겨 ^^; 좀 더 살펴봤습니다.

우선 예를 들기 위해 다음의 코드로 시작해 보겠습니다.

using System;

namespace ConsoleApp2
{
    class ABC
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            Dump(new ABC());
        }

        private static void Dump(ABC aBC)
        {
            Console.ReadLine();
        }
    }
}

아무것도 정의하지 않은 ABC 클래스이지만 DumpClass로 살펴보면,

0:000> !DumpClass 00cf16ec
Class Name:      ConsoleApp2.ABC
mdToken:         02000002
File:            F:\cloud_drive\Dropbox\articles\compoentSize\ConsoleApp2\ConsoleApp2\bin\Debug\ConsoleApp2.exe
Parent Class:    715445e0
Module:          00cf3ffc
Method Table:    00cf4d88
Vtable Slots:    4
Total Method Slots:  5
Class Attributes:    100000  
Transparency:        Critical
NumInstanceFields:   0
NumStaticFields:     0

"Vtable Slots == 4", "Total Method Slots == 5"가 나옵니다.

우선 결론부터 설명하면 "Vtable Slots"은 가상 함수의 수를 의미합니다. 그런데 어떻게 ABC 클래스에 4개가 있을까요? Visual Studio에서 object 타입에 대해 F12 키를 눌러 메타데이터 정의로 들어가 보면 다음과 같이 3개의 가상 함수를 확인할 수 있습니다.

using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;

namespace System
{
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(true)]
    public class Object
    {
        [NonVersionableAttribute]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        public Object();

        [NonVersionableAttribute]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        ~Object();

        [NonVersionableAttribute]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static bool ReferenceEquals(Object objA, Object objB);
        public virtual bool Equals(Object obj);
        public virtual int GetHashCode();
        [SecuritySafeCritical]
        public Type GetType();
        public virtual string ToString();
        [SecuritySafeCritical]
        protected Object MemberwiseClone();
    }
}

아니, 그런데 분명히 "Vtable Slots"의 값은 4로 나오는데 어째서 3일까요? 왜냐하면 ~Object로 표현된 소멸자가 실은 다음과 같이 가상 함수이기 때문입니다.

// .NET Reflector 등을 통해 보면 virtual 메서드로 나옴

protected virtual void Finalize();

따라서 windbg의 출력 결과인 4가 맞습니다. 그렇다면 "Vtable Slots"이 가상 함수의 수라는 것은 알겠는데 뜬금없이 "Total Method Slots == 5"가 나오는 것은 왜일까요?

그것은 기본 생성자(ctor)와 기본 정적 생성자(cctor)가 "Total Method Slots"의 수에 포함되기 때문입니다. ABC 클래스의 경우 기본 생성자가 정의되어 있기 때문에 5가 나오는 것입니다. 그런데 재미있는 것은 일반 생성자를 하나 정의해서 기본 생성자의 자동 추가를 막게 되면,

class ABC
{
    public ABC(char ch) { }
}

이번에는 ctor가 없어졌으므로 다음과 같은 상태로 바뀝니다.

Vtable Slots = 4
Total Method Slots = 4

물론 다시 기본 생성자를 추가하면 Total Method Slots는 5로 바뀝니다.

class ABC
{
    public ABC(char ch) { }
    public ABC() { }
}

/*
Vtable Slots = 4
Total Method Slots = 5
*/

즉, 다른 생성자들은 전혀 상관이 없고 오직 기본 생성자에 한해서만 Total Method Slots의 수가 바뀌는 것입니다.

마찬가지로 정적 생성자도 Total Method Slots의 수에 반영됩니다.

class ABC
{
    public ABC(char ch) { }
    public ABC() { }

    // 또는 정적 생성자가 생성되도록 유발하는 정적 필드 초기화가 있는 경우에도!
    static ABC()
    {
    }
}
/*
Vtable Slots = 4
Total Method Slots = 6
*/




자, 그럼 이 지식들을 바탕으로 System.String을 다시 볼까요? ^^

정리하면 System.String은 다음과 같은 수치를 보입니다.

Vtable Slots:    1b (0n27)
Total Method Slots:  1d (0n29)
Slots in VTable: 194

그럼 수치들을 한번 맞춰보겠습니다. 우선 string은 다음과 같은 가상 메서드들을 구현하고 있습니다.

System.Object로부터 4개
IComparable로부터 1개
ICloneable로부터 1개
IConvertible로부터 17개
IEnumerable로부터 1개
IComparable<String>로부터 1개
IEnumerable<char>로부터 1개
IEquatable<String>로부터 1개
====
총 27개

그렇다면 "Vtable slots = 0x1b(0n27)"은 만족합니다. 그런데 Total Method Slots의 수가 29가 나오다니... 이건 좀 이상하군요. 분명히 System.String에는 기본 생성자도, 정적 생성자도 없기 때문에 Total Method Slots의 수도 27이 나와야 맞습니다.

당연하겠지만 여기서 고려하지 않은 조건이 있습니다. 바로 '제네릭' 메서드가 "Total Method Slots"에 반영된다는 점입니다. System.String을 보면 이런 메서드로 2개가 나옵니다.

public static String Join<T>(String separator, IEnumerable<T> values);
public static String Concat<T>(IEnumerable<T> values);

따라서 이것까지 고려해 Total Method Slots = 29가 나오는 것입니다.

확인을 위해 ABC 클래스를 이용해 다음과 같이 테스트해 볼 수 있습니다.

class ABC
{
    public ABC(char ch) { }
    public ABC() { }

    static ABC()
    {
    }

    void Test<T>(List<T> arg) { }
    void Test2<T>(List<T> arg) { }
}

/*
Vtable Slots = 4
Total Method Slots = 8 (Vtable Slots 4 + default ctor 1 + cctor 1 + generic method 2)
*/

정리가 되고 나니... 저도 마음이 편하군요. ^^




참고로, !DumpMT -md 명령어는 Vtable Slots, Total Method Slots, Slots in VTable에 속하는 메서드의 종류별로 묶어서 출력을 해줍니다. 가령 ABC 클래스를 다음과 같이 정의해 주면,

class ABC
{
    public ABC(char ch) { }
    public ABC() { }

    static ABC()
    {
    }

    void Test<T>(List<T> arg) { }
    void Test2<T>(List<T> arg) { }

    void MyMethod() { }
    static void StaticMyMethod() { }
}

!DumpMT -md의 출력은 다음과 같이 분류가 되어 출력됩니다.

the_number_of_method_1.png




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/10/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 181  182  183  184  185  186  [187]  188  189  190  191  192  193  194  195  ...
NoWriterDateCnt.TitleFile(s)
286정성태6/23/200622407웹: 4. 웹 사이트 식별자(Identifier) 값 변경
285정성태6/20/200622653오류 유형: 9. [TFS] Report 관련 서비스를 조회할 때 rsErrorImpersonatingUser 오류 메시지 발생 [1]
284정성태6/19/200620419VS.NET IDE: 40. FxCop - IDE 에서 제공해 주는 SuppressMessage 코드
283정성태1/19/200721304Team Foundation Server: 8. 소스 세이프에서 TFS SourceControl 로 마이그레이션 [2]
279정성태12/27/200626694개발 환경 구성: 3. VS.NET 원격 디버깅 [1]
280정성태6/12/200626166    답변글 개발 환경 구성: 3.1. VS.NET 2003 원격 디버깅 설정
281정성태8/11/200627648    답변글 개발 환경 구성: 3.2. VS.NET 2005 원격 디버깅 설정
315정성태8/11/200628285        답변글 개발 환경 구성: 3.3. VS.NET 2005 원격 디버깅 설정 - ASP.NET F5 디버깅
278정성태6/11/200624851오류 유형: 8. [Outlook] 0x8004011D 에러 - "Exchange over the Internet" 환경
276정성태6/7/200618297Team Foundation Server: 7. 외부 빌드 머신 구성
287정성태6/24/200615943    답변글 Team Foundation Server: 7.1. 외부 빌드 머신 구성 - 다른 블로그 자료
275정성태6/7/200623842디버깅 기술: 4. VC++ 8.0 원격 디버깅 구성 - Side-by-Side DLL 문제.
269정성태6/6/200621030Team Foundation Server: 6. HTTPS를 통한 Team Server 접근 [1]
270정성태6/5/200617990    답변글 Team Foundation Server: 6.1. HTTPS를 통한 Team Server 접근 [1]
273정성태6/6/200620728    답변글 Team Foundation Server: 6.2. 두번째 방법 - HTTPS 를 통한 Team Server 접근 [1]
267정성태6/4/200620037Team Foundation Server: 5. 인터넷으로 Team Server 접근 [2]
266정성태6/8/200616635오류 유형: 7. [설치] mpoai9.dll 관련 오류
265정성태6/1/200624378디버깅 기술: 3. 원격 컴퓨터 디버깅 - VPC 설정
314정성태8/11/200621455    답변글 디버깅 기술: 3.1. Managed 원격 디버깅과 WinDBG 원격 디버깅
264정성태6/1/200630555오류 유형: 6. [VC++ 컴파일] already defined in ntdll.lib(ntdll.dll)
263정성태6/1/200631466디버깅 기술: 2. 커널 구조체 살펴보기 [5]
262정성태6/1/200623858오류 유형: 5. [설치] WinFX Beta2 - 설치시 문제점 해결
261정성태6/1/200620311웹: 3. IIS 6.0 - AppPool을 활용하여 실 서버(운영 서버)에서 디버깅
258정성태6/1/200628222디버깅 기술: 1. 디버깅 방법 - CLR 프로파일러 [1]파일 다운로드1
274정성태6/7/200621135    답변글 디버깅 기술: 1.1. 디버깅 방법 - CLR 프로파일러 ( on Vista )
254정성태6/1/200617590개발 환경 구성: 2. VPC에 Vista 설치하는 방법 [2]
... 181  182  183  184  185  186  [187]  188  189  190  191  192  193  194  195  ...