wenmo8 发布的文章

有人在论坛上问过关于在混合模式下编辑并继续(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将特定方法标记为非用户代码。

什么是std::length_error异常

长度错误。它报告由于试图超出某些对象的实现定义的长度限制而导致的错误。一般由std::basic_string和std::vector::reserve等成员函数抛出。

继承关系

 

异常结构填充

ExceptionAddress: 747cc5af (KERNELBASE!RaiseException+0x00000058)
   ExceptionCode: e06d7363 (C++ EH exception)
  ExceptionFlags: 00000001
NumberParameters: 3
   Parameter[0]: 19930520
   Parameter[1]: 0039a178//std::length_error对象指针
   Parameter[2]: 66805744


0:000> dt std::length_error 0039a178
DIYHome!std::length_error
   +0x000 __VFN_table : 0x667c147c
   +0x004 _Mywhat          : 0x154882d8  "vector<T> too long"
   +0x008 _Mydofree   

备注

这个异常既不是内存不够,也不是越界,而是要生成的容器size超过了容器最大值(max_size())而引发。当然引起超过最大值的原因就多种多样了。