성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>windbg - SOS DumpClass/DumpMT의 "Vtable Slots", "Total Method Slots", "Slots in VTable" 값에 대한 의미</h1> <p> windbg에서 System.String 타입에 대해 DumpClass 명령을 수행해 보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> <span style='color: blue; font-weight: bold'>!DumpClass 00007ff961df50e0</span> 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 <span style='color: blue; font-weight: bold'>Vtable Slots: 1b Total Method Slots: 1d</span> 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 << </pre> <br /> 위와 같이 "Vtable Slots"와 "Total Method Slots" 값이 나옵니다. "Vtable"이라는 단어로 봐서 분명 가상 메서드와 관련이 있을 것 같은데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C++의 가상 함수 테이블 (vtable)은 언제 생성될까요? ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11167'>http://www.sysnet.pe.kr/2/0/11167</a> C++ 클래스 상속 관계의 vtable 생성 과정 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11168'>http://www.sysnet.pe.kr/2/0/11168</a> </pre> <br /> 2개로 나누어져 있는 이유를 모르겠습니다. 게다가 DumpMT로 System.String 타입의 메서드 테이블을 살펴보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> <span style='color: blue; font-weight: bold'>!DumpMT 00007ff9624f6948</span> 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 <span style='color: blue; font-weight: bold'>Slots in VTable: 194</span> Number of IFaces in IFaceMap: 7 </pre> <br /> "Slots in VTable"이란 값도 나옵니다. 이렇게 3가지로 나누어져 있다 보니 더욱 혼란스럽습니다. ^^;<br /> <br /> 이 중에서 "Slots in VTable"은 "!DumpMT -md <addr>" 명령을 내리면 그 의미를 확실히 알 수 있습니다. 왜냐하면 실제로 194개의 메서드 목록이 나오기 때문입니다. 그럼 한 가지는 정리되었군요. ^^ "Slots in VTable" 값이야말로 해당 타입이 (상속을 포함해) 소유하고 있는 전체 메서드의 수를 가리킵니다.<br /> <br /> 남은 것은 "Vtable Slots"와 "Total Method Slots"의 의미인데요. 이게 좀 재미있습니다. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로 검색해 보면 다음과 같은 질문 글이 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > SOS and DumpClass ; <a target='tab' href='https://social.msdn.microsoft.com/Forums/vstudio/en-US/13839da8-bc06-4443-9a1b-5e326e386ff8/sos-and-dumpclass?forum=clr'>https://social.msdn.microsoft.com/Forums/vstudio/en-US/13839da8-bc06-4443-9a1b-5e326e386ff8/sos-and-dumpclass?forum=clr</a> </pre> <br /> 정리하면, 너무 난이도가 있는 질문이라 더 진행하려면 "유료" 기술 지원을 신청해야 한다는 답변이 나옵니다. 그래서 저도 그냥 접을까 하다가 호기심이 생겨 ^^; 좀 더 살펴봤습니다.<br /> <br /> 우선 예를 들기 위해 다음의 코드로 시작해 보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; namespace ConsoleApp2 { <span style='color: blue; font-weight: bold'>class ABC { }</span> class Program { static void Main(string[] args) { Dump(new ABC()); } private static void Dump(ABC aBC) { Console.ReadLine(); } } } </pre> <br /> 아무것도 정의하지 않은 ABC 클래스이지만 DumpClass로 살펴보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> <span style='color: blue; font-weight: bold'>!DumpClass 00cf16ec</span> 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 <span style='color: blue; font-weight: bold'>Vtable Slots: 4 Total Method Slots: 5</span> Class Attributes: 100000 Transparency: Critical NumInstanceFields: 0 NumStaticFields: 0 </pre> <br /> "Vtable Slots == 4", "Total Method Slots == 5"가 나옵니다.<br /> <br /> 우선 결론부터 설명하면 "Vtable Slots"은 가상 함수의 수를 의미합니다. 그런데 어떻게 ABC 클래스에 4개가 있을까요? Visual Studio에서 object 타입에 대해 F12 키를 눌러 메타데이터 정의로 들어가 보면 다음과 같이 3개의 가상 함수를 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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); <span style='color: blue; font-weight: bold'>public virtual bool Equals(Object obj); public virtual int GetHashCode();</span> [SecuritySafeCritical] public Type GetType(); <span style='color: blue; font-weight: bold'>public virtual string ToString();</span> [SecuritySafeCritical] protected Object MemberwiseClone(); } } </pre> <br /> 아니, 그런데 분명히 "Vtable Slots"의 값은 4로 나오는데 어째서 3일까요? 왜냐하면 ~Object로 표현된 소멸자가 실은 다음과 같이 가상 함수이기 때문입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // .NET Reflector 등을 통해 보면 virtual 메서드로 나옴 protected <span style='color: blue; font-weight: bold'>virtual</span> void Finalize(); </pre> <br /> 따라서 windbg의 출력 결과인 4가 맞습니다. 그렇다면 "Vtable Slots"이 가상 함수의 수라는 것은 알겠는데 뜬금없이 "Total Method Slots == 5"가 나오는 것은 왜일까요?<br /> <br /> 그것은 기본 생성자(ctor)와 기본 정적 생성자(cctor)가 "Total Method Slots"의 수에 포함되기 때문입니다. ABC 클래스의 경우 기본 생성자가 정의되어 있기 때문에 5가 나오는 것입니다. 그런데 재미있는 것은 일반 생성자를 하나 정의해서 기본 생성자의 자동 추가를 막게 되면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class ABC { public ABC(char ch) { } } </pre> <br /> 이번에는 ctor가 없어졌으므로 다음과 같은 상태로 바뀝니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Vtable Slots = 4 Total Method Slots = 4 </pre> <br /> 물론 다시 기본 생성자를 추가하면 Total Method Slots는 5로 바뀝니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class ABC { public ABC(char ch) { } public ABC() { } } /* Vtable Slots = 4 Total Method Slots = 5 */ </pre> <br /> 즉, 다른 생성자들은 전혀 상관이 없고 오직 기본 생성자에 한해서만 Total Method Slots의 수가 바뀌는 것입니다.<br /> <br /> 마찬가지로 정적 생성자도 Total Method Slots의 수에 반영됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class ABC { public ABC(char ch) { } public ABC() { } // 또는 정적 생성자가 생성되도록 유발하는 정적 필드 초기화가 있는 경우에도! static ABC() { } } /* Vtable Slots = 4 Total Method Slots = 6 */ </pre> <br /> <hr style='width: 50%' /><br /> <br /> 자, 그럼 이 지식들을 바탕으로 System.String을 다시 볼까요? ^^<br /> <br /> 정리하면 System.String은 다음과 같은 수치를 보입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Vtable Slots: 1b (0n27) Total Method Slots: 1d (0n29) Slots in VTable: 194 </pre> <br /> 그럼 수치들을 한번 맞춰보겠습니다. 우선 string은 다음과 같은 가상 메서드들을 구현하고 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > System.Object로부터 4개 IComparable로부터 1개 ICloneable로부터 1개 IConvertible로부터 17개 IEnumerable로부터 1개 IComparable<String>로부터 1개 IEnumerable<char>로부터 1개 IEquatable<String>로부터 1개 ==== 총 27개 </pre> <br /> 그렇다면 "Vtable slots = 0x1b(0n27)"은 만족합니다. 그런데 Total Method Slots의 수가 29가 나오다니... 이건 좀 이상하군요. 분명히 System.String에는 기본 생성자도, 정적 생성자도 없기 때문에 Total Method Slots의 수도 27이 나와야 맞습니다.<br /> <br /> 당연하겠지만 여기서 고려하지 않은 조건이 있습니다. 바로 '제네릭' 메서드가 "Total Method Slots"에 반영된다는 점입니다. System.String을 보면 이런 메서드로 2개가 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public static String Join<T>(String separator, IEnumerable<T> values); public static String Concat<T>(IEnumerable<T> values); </pre> <br /> 따라서 이것까지 고려해 Total Method Slots = 29가 나오는 것입니다.<br /> <br /> 확인을 위해 ABC 클래스를 이용해 다음과 같이 테스트해 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class ABC { public ABC(char ch) { } <span style='color: blue; font-weight: bold'>public ABC() { }</span> <span style='color: blue; font-weight: bold'>static ABC()</span> { } <span style='color: blue; font-weight: bold'>void Test<T>(List<T> arg) { }</span> <span style='color: blue; font-weight: bold'>void Test2<T>(List<T> arg) { }</span> } /* Vtable Slots = 4 Total Method Slots = 8 (Vtable Slots 4 + default ctor 1 + cctor 1 + generic method 2) */ </pre> <br /> 정리가 되고 나니... 저도 마음이 편하군요. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, !DumpMT -md 명령어는 Vtable Slots, Total Method Slots, Slots in VTable에 속하는 메서드의 종류별로 묶어서 출력을 해줍니다. 가령 ABC 클래스를 다음과 같이 정의해 주면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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() { } } </pre> <br /> !DumpMT -md의 출력은 다음과 같이 분류가 되어 출력됩니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='the_number_of_method_1.png' src='/SysWebRes/bbs/the_number_of_method_1.png' /><br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
5212
(왼쪽의 숫자를 입력해야 합니다.)