为什么对于同一个进程,小型转储有时只有调用堆栈?
Why do minidumps only sometimes have call stacks, for the same process?
最近我们在生产中遇到了问题。我使用 ProcessExplorer 对其进行调试,在 cdb 中保存了一个小型转储并在 VS2015 中对其进行了分析。我可以在主线程上看到 clr 调用堆栈,其中包含我们代码中的符号。
为了学习更多,我创建了一个简单的程序,它会挂起(带有一些调用堆栈),如下所示(在 Release 中构建,构建后移动了源代码):
public class Program
{
public static void Main(string[] args)
{
new Program().Run();
}
public void Run()
{
DoThing();
}
public void DoThing()
{
Task t = new Task(() =>
{
while (true)
{
}
}
);
t.RunSynchronously();
}
}
我随后通过三种方式创建了转储文件:
- 通过任务管理器
- 附加 cdb 和 .dump /ma
- 附加到 VS2015,破坏并保存转储文件
所有转储的大小都非常相似。当我在新的 VS2015 会话中打开它们时,只有最后一个方法向我显示主线程的 clr 调用堆栈。为什么是这样?我在 VS 中保存转储时没有看到调用堆栈,但是当我重新打开转储文件时看到了。
我如何保证在生产中创建转储时可以看到 clr 调用堆栈(当 VS 不可用时)。
另外,当我第一次使用 ProcessExplorer 和 cdb 在生产中创建转储文件时,为什么会得到 clr 调用堆栈?
更新:
我检查了转储文件中的字符串,它们都包含如下值:
<做事>b__2_0
做事
做事>b__2_0
我的问题是任务管理器或 cdb 创建的小型转储有主线程堆栈,例如:
ntdll.dll!778214d1()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
mscorlib.ni.dll!7279bbc0()
而由 visual studio 创建的主线程堆栈如下:
DumpDiag.exe!DumpDiag.Program.DoThing.AnonymousMethod__2_0()
mscorlib.dll!System.Threading.Tasks.Task.InnerInvoke()
mscorlib.dll!System.Threading.Tasks.Task.Execute()
这是因为我的 .net 进程是 32 位的,但我用 cdb 和任务管理器捕获的小型转储是 64 位的。我错误地使用了 x64 版本的 cdb,以及捕获 64 位转储的(默认)64 位任务管理器。
我在上面创建了单独的 32 位和 64 位版本的测试过程,并使用相关版本的 cdb、相关版本的任务管理器以及附加 Visual Studio 捕获了小型转储。此后所有转储都正确显示了 clr 调用堆栈。
最近我们在生产中遇到了问题。我使用 ProcessExplorer 对其进行调试,在 cdb 中保存了一个小型转储并在 VS2015 中对其进行了分析。我可以在主线程上看到 clr 调用堆栈,其中包含我们代码中的符号。
为了学习更多,我创建了一个简单的程序,它会挂起(带有一些调用堆栈),如下所示(在 Release 中构建,构建后移动了源代码):
public class Program
{
public static void Main(string[] args)
{
new Program().Run();
}
public void Run()
{
DoThing();
}
public void DoThing()
{
Task t = new Task(() =>
{
while (true)
{
}
}
);
t.RunSynchronously();
}
}
我随后通过三种方式创建了转储文件:
- 通过任务管理器
- 附加 cdb 和 .dump /ma
- 附加到 VS2015,破坏并保存转储文件
所有转储的大小都非常相似。当我在新的 VS2015 会话中打开它们时,只有最后一个方法向我显示主线程的 clr 调用堆栈。为什么是这样?我在 VS 中保存转储时没有看到调用堆栈,但是当我重新打开转储文件时看到了。
我如何保证在生产中创建转储时可以看到 clr 调用堆栈(当 VS 不可用时)。 另外,当我第一次使用 ProcessExplorer 和 cdb 在生产中创建转储文件时,为什么会得到 clr 调用堆栈?
更新:
我检查了转储文件中的字符串,它们都包含如下值:
<做事>b__2_0
做事
做事>b__2_0
我的问题是任务管理器或 cdb 创建的小型转储有主线程堆栈,例如:
ntdll.dll!778214d1()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
mscorlib.ni.dll!7279bbc0()
而由 visual studio 创建的主线程堆栈如下:
DumpDiag.exe!DumpDiag.Program.DoThing.AnonymousMethod__2_0()
mscorlib.dll!System.Threading.Tasks.Task.InnerInvoke()
mscorlib.dll!System.Threading.Tasks.Task.Execute()
这是因为我的 .net 进程是 32 位的,但我用 cdb 和任务管理器捕获的小型转储是 64 位的。我错误地使用了 x64 版本的 cdb,以及捕获 64 位转储的(默认)64 位任务管理器。
我在上面创建了单独的 32 位和 64 位版本的测试过程,并使用相关版本的 cdb、相关版本的任务管理器以及附加 Visual Studio 捕获了小型转储。此后所有转储都正确显示了 clr 调用堆栈。