《C#从现象到本质》第四章提到了方法表,感觉是语言里很精华的部分,比光学语法规则有趣多了。书里直奔主题(其实是人菜瘾大还爱跳读),被绊了几天,好气哇(书的第二章有提到如何使用WinDbg)。
旧是旧了点,也能用。方法二里的WinDbg Preview是新版,这是旧版。
参考 Download Debugging Tools for Windows - WinDbg - Windows drivers | Microsoft Docs
打开Microsoft Store,搜索windbg,
点击安装,用了全局代理才安装到,这里大家就八仙过海的下一句。
创建项目-c#控制台应用(.Net Framework),名为ConsoleApp2
项目保存路径为:E:\c#\ConsoleApp2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class A
{
public virtual void Foo()
{
Console.WriteLine("A.Foo");
}
}
class B:A
{
public virtual void Foo()
{
Console.WriteLine("B.Foo");
}
}
class C : B
{
public override void Foo()
{
Console.WriteLine("C.Foo");
}
}
internal class Program
{
static void Main(string[] args)
{
A a = new A();
a.Foo();
A b = new B();
b.Foo();
A c = new C();
c.Foo();
Console.WriteLine(typeof(A).FullName);
}
}
}
参考:Windbg 32位版本和64位版本的选择_ithzhang的博客-CSDN博客_windbg64
打开WinDbg-File-Open Executable
选中需要调试的程序,打开
输入lm,回车,看看加载了什么模块
lm
使用sympath命令,设置pdb所在路径,回车
.sympath E:\c#\ConsoleApp2\bin\Debug
调用g命令运行程序,回车
g
使用load命令加载sos.dll,(注意sos.dll的路径和上面一步画线的clr.dll路径是一致的,C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll)
.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
如果没加载 sos.dll,使用name2ee命令,会输出No export name2ee found
使用name2ee获取类A方法表地址,输入以下命令,回车
!name2ee ConsoleApp2 ConsoleApp2.A
使用dumpmt命令, 查看方法表。输入以下命令,回车
!dumpmt -md 00704dd0
打开winDbg Preview -文件
选择需要调试的程序
按Go按钮,或者使用g命令,回车,发现加载了clr模块
参考SOS.dll (SOS Debugging Extension) - .NET Framework | Microsoft Docs
使用name2ee命令,获取类的EEClass地址。
输入以下命令,回车。
!name2ee ConsoleApp2 ConsoleApp2.A
使用!dumpmt命令,查看方法表
输入以下命令,回车
!dumpmt -md 00ff4dd0
参考 WinDbg 入门(用户模式) - Windows drivers | Microsoft Docsc
命令 | 描述 | 参考 |
.load | 加载新的扩展 DLL 到调试器中 格式:.load DLLName 例子:.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll |
.load、.loadby(加载扩展 DLL) - Windows drivers | Microsoft Docs |
.loadby | 加载新的扩展 DLL 到调试器中 格式:.loadby DLLName ModuleName 例子:.loadby sos clr |
.load、.loadby(加载扩展 DLL) - Windows drivers | Microsoft Docs |
.sympath | 指定 WinDbg 查找符号 (PDB) 文件的位置; 格式:.sympath[+] [Path [; ...]] 例子:.sympath E:\c#\ConsoleApp2\bin\Debug |
.sympath(设置符号路径) - Windows drivers | Microsoft Docs |
.reload | 通知 WinDbg 进行符号文件的初始查找和加载 | .reload(重新加载模块) - Windows drivers | Microsoft Docs |
bu | 设置断点; 格式:bu 程序名!函数名 例子:bu notepad!wWinMain |
bp、bu、bm(设置断点) - Windows drivers | Microsoft Docs |
lm | 查看进程中加载的代码模块列表 | lm(列出已加载的模块) - Windows drivers | Microsoft Docs |
g | 运行 | g(转到) - Windows drivers | Microsoft Docs |
k | 查看堆栈跟踪 | k、kb、kc、kd、kp、kP、kv(显示堆栈回溯) - Windows drivers | Microsoft Docs |
q | 退出进程 | q、qq(退出) - Windows drivers | Microsoft Docs |
qd | 退出调试并从进程分离 | qd(退出和分离) - Windows drivers | Microsoft Docs |
参考SOS.dll (SOS Debugging Extension) - .NET Framework | Microsoft Docs
语法格式:![command] [options]
命令 | 描述 | 格式 | 例子 |
Name2EE | 显示指定模块中指定类型或方法的MethodTable结构和结构。 指定的模块必须在进程中加载。 要获得正确的类型名称,请使用Ildasm.exe (IL Disassembler)浏览模块。 |
Name2EE <模块名称> <类型或方法名称> -或 | !name2ee ConsoleApp2 ConsoleApp2.A |
DumpMT | 显示有关指定地址的方法表的信息。 指定-MD选项会显示使用对象定义的所有方法的列表。 |
DumpMT [ -MD ] <方法表地址> | !dumpmt -md 00704dd0 |
c#类的方法表的建立和方法的调用 - seeseaatsea - 博客园对于方法的调用,很是令我头疼,什么静态方法,实例方法,实例虚方法,这里查了很多资料,总结如下: 这里声明,我也是菜鸟,这里只讨论方法的调用相关的技术,属于个人理解,如有错误,请指正 思路: 1 clrhttps://www.cnblogs.com/OneRipple/p/7093876.html
上面链接的内容对我理解方法表帮助蛮大的,在这里马一下。
方法在方法表中的排列顺序:
继承的实例虚方法、实例虚方法、构造函数、静态方法、实例方法
为什么把“继承的实例虚方法”和“实例虚方法”放在方法表的开头位置?
结论:方法表中虚方法的排序,可以在类的层次结构中保持虚方法的层次结构,这是实现多态的基础,也就是为什么说继承是实现多态的基础了。