wenmo8 发布的文章

!clrstack输出,如下所示:

0:019> !clrstack 
OS Thread Id: 0x5d0 (19) 
ESP      EIP 
0f31f340 7c80bef7 [HelperMethodFrame_1OBJ: 0f31f340] 
0f31f398 1449167a 
0f31f3c4 144915e6 
0f31f3f4 10d81b48 
0f31f4b4 793e25cf 
0f31f4bc 79366b3d 
0f31f4d4 793e2734 
0f31f4e8 793e26ac 
0f31f678 79e7c0e3 [GCFrame: 0f31f678]

需要做一些事情来解决这个问题。

正确版本的MSCORDACWKS.dll

你可以用两种方法得到这个

将符号路径设置为srv*c:\mycache*http://msdl.microsoft.com/download/symbols

或者

通过从获取转储的计算机上复制它,它将位于Framework\<version>目录中。这个mscordacwks.dll需要复制到您的符号路径,如果您使用多个版本,并区分它们,您可以将其命名为mscordacwks_x86_x86_2.0.50727.42.dll。在我的机器上,因为我使用的版本太多了,所以我有一个c:\dac\x86和一个c:\dac\x64目录来存储这些文件。

兼容版本的sos.dll

sos.dll可以在framework\<version>目录中找到,并且需要与转储中使用的框架的体系结构和主要版本相匹配。如果您的计算机上的框架的次要版本与您获取转储的计算机之间的差异太大,可以尝试复制机器上。也可以使用psscor2.dll。

 

有人在论坛上问过关于在混合模式下编辑并继续(EnC)的问题。不能在启用混合模式(interop)调试的情况下使用托管EnC。这是CLR调试服务的一个限制。互操作调试和EnC都是复杂的特性;将它们结合起来将是一个巨大的测试矩阵,而且成本非常高。因此,如果你有C和本地C++解决方案,你的选择是:

人们可以使用术语“模块时间戳”来表示文件时间戳和Image头时间戳。虽然他们通常非常接近,但他们是不同的,不会是相同的。下面是一个比较/对比:

File timestamp Image header timestamp
What is it? This is tracked by the file system, and includes several metrics such as when the file was created, when it was last modified, and when it was last accessed. Emitted by the compiler and stored in the image header. Thus, it's in the contents of the file and separate from the meta-information tracked by the filesystem.
Who normally sets it? The file system. The compiler (which then generally creates a file to persists the results to, thus the file and image timestamps are usually very close)
Underlying storage 64-bit FileTime structure 32-bit time_t structure.
Win32 exposure kernel32!GetFileTime IMAGE_FILE_HEADER, exposed via the ImageHelp library.Matt Pietrek has an excellent article about cracking the PE file to get information like this. (The PE file format is publicly specced).
.NET exposure In .NET, these are accessible as System.DateTime objects via File.GetCreationTime, File.GetLastAccessTime, File.GetLastWriteTime. I don't think there are any .Net APIs to get these. (does anybody want them?).  The Pdb2Xml writer in MDbg sample alludes to this a little.BradA tells how to convert time_t to a System.DateTime.    

映像时间戳是您在调试器下看到的。例如,windbg的“lmv”命令将时间戳显示为原始32位值,并将其转换为有用的值:

Image name: notepad.exe
Timestamp: Tue Aug 03 23:05:55 2004 (41107CC3)
CheckSum: 00014F7F

可以从资源管理器查看文件时间戳。右键单击该文件并显示属性。为了进行比较,来自同一文件的时间戳通过文件系统:

创建时间:2004年8月9日星期一上午11:11:33

修改日期:2004年8月4日星期三上午4:00:00

访问时间:今天,2007年1月18日,晚上7:22:56


映像时间戳(和其他相关数据)也是转储文件中捕获的内容(请参阅MINIDUMP_MODULE)。因此,当调试器希望将小型转储中的模块与磁盘上的实际模块关联时,它可以使用映像头中的时间戳和校验和。这与PDB匹配的工作原理类似。

 

问题是:
也许您在调试时浏览了全局、局部或参数,然后通过一些丑陋的对象引用(如哈希表)来查找对象引用。你希望能在那个物体上获得一些身份,这样你就可以很容易地再次找到它。以后重新查找它可能不实际,特别是如果程序状态自上次以来已更改,以致原始步骤不再生成相同的对象。如果一个数据结构被更改,一个变量被重新分配,或者一个函数返回并使其所有的局部变量无效,那么很容易发生这种情况。事实上,在这种情况下,回溯原始步骤甚至可能产生完全不同的对象。
解决方案是提供独立于其发现方式的“对象标识”。然后,不管程序状态发生了什么变化,都可以在以后根据其标识检索对象

本机代码中的对象标识

在本机代码中,通过“this”指针,每个对象都有一个内部标识。由于本机代码中没有GC移动对象,所以对象的地址是常量,只要对象还活着,就可以用来引用对象。


例如,如果我知道地址0x0012eeff有一个Foo类型的对象,我可以通过检查“((Foo*)0x0012eeff)”随时查看它。地址提供了一个非常方便的固有对象标识。

托管代码中的问题

由于托管代码有一个GC来移动对象,所以转换地址不一定是安全的。地址可以是0x0012eeff,然后GC可以将其移动到0x44556677。托管代码的任何对象标识解决方案都需要与垃圾回收器协作。

托管代码中的对象标识示例

有时开发人员只想调试他们编写的代码,而不想调试应用程序中的第三方代码(如框架和库)。当用户和非用户代码在彼此之间来回调用时,这一点尤其有用。clr调试服务有许多新特性来支持这一点,我们称之为“Just My Code”(JMC)调试。

允许调试器将每个函数标记为用户代码或非用户代码。由调试器决定哪些是用户代码,哪些不是用户代码。visualstudio将使用来自项目系统的提示,如果缺少符号,还将假定给定模块是否为非用户代码。您也可以使用System.Diagnostics.DebuggerNonUserCodeAttribute属性告诉VS将特定方法标记为非用户代码。