无法在互操作调试上进行编辑并继续进
Image Header vs. File Timestamps.
人们可以使用术语“模块时间戳”来表示文件时间戳和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)调试。
关于std::length_error异常
什么是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())而引发。当然引起超过最大值的原因就多种多样了。