使用以下简单文件:
using System;
public class Program{
[STAThread]
public static void Main(string[] args){
Console.WriteLine("Boo");
}
}
然后使用以下命令:
csc /target:exe /debug:pdbonly HelloWorld.cs
如果运行此命令且PDB尚不存在,则PDB文件大小为12KB。否则,如果PDB文件存在,则新文件大小为14KB。
Microsoft (R) Visual C# Compiler version 4.0.30319.17929
.NET 4.5
任何人都有什么想法可以解释这个?
更新
答案 0 :(得分:18)
我的回答很简单,但也许不那么准确。 让我们在PDB文件上使用一个调试工具:
唯一的区别是PdbAge
字段。这意味着每次编译后PDB文件未重新创建!此文件已被修改,这就是它的大小更改的原因。
我的猜测已在此article中得到确认。 引用:
格式变化的最重要动机之一是 允许增量链接调试版本的程序,一个更改 首先在Visual C ++版本2.0中引入。
另一个问题是这个文件究竟发生了什么变化?我在“Sven B. Schreiber, “Undocumented Windows 2000 Secrets: A Programmer’s Cookbook””一书中找到的文件格式的最详细解释。关键词是:
PDB格式的更大好处变得明显 更新现有的PDB文件。使用a将数据插入文件 顺序结构通常意味着重组大部分 内容。 PDB文件的随机访问结构是从文件中借来的 系统允许以最小的努力添加和删除数据 因为文件可以在文件系统媒体上轻松修改。只有 当流增长或收缩时,必须重新整理流目录 跨越页面边界。这个重要的财产便利 增量更新PDB文件。
他描述并非文件中的所有数据在每个时刻都有用。某些字节范围只是由零填充,直到在下次编译期间修改该文件。
所以除了一些GUID和年龄编号之外,我无法分辨PDB文件中的完全是什么。读完那本书后你可以更深入了解。祝你好运!
更新(2013年3月15日):
我花了一些时间来比较文件。当我在HEX模式下打开它时,我看到标题中的差异: 文件的页面大小为512字节(+ 20h时为200h),页面数量不同: 120和124(相应地为078h和07Ch)。在我的屏幕上,较小的文件位于左侧。 好。文件大小的差异恰好是2048字节。这意味着编译器第二次添加4页数据。 然后我找到了所有其他的差异。从开始的3/4文件包含小差异 - 像往常一样几个字节。但在2600h,我们看到:
看!第/LinkInfo./names./src/files/c:\Windows\microsoft.net\framework\v4.0.30319\helloworld.cs
行被裁剪,现在包含不一致的信息。
我期待并在第二个(更大)文件中找到完整表示的这一行: 此信息现在被放置到自由空间(请参见左侧的零)。 我想,旧页面(带有损坏的字符串)被标记为未使用的空间。
在文件末尾,我发现了正确的2048字节的新信息 - 都是零。从2E00h开始(十进制11776),结束于35F8h(十进制13816)。我们记得,第一个文件的大小正好是11776字节。
作为结论:我认为较大的文件不包含任何新信息。但我仍然无法回答为什么编译器将4个空页面的数据添加到ProgramDataBase文件的末尾。我认为这些知识是编译器开发人员的秘密。
答案 1 :(得分:2)
Simon Mourier的评论几乎肯定是正在发生的事情。在编译器的第二次运行时,PDB文件被更新,并且该更新的结果在PDB内留下“已删除”或未使用的块。在后续构建中,不是为更新分配新页面,而是重用未使用的页面(在此过程中创建另一组未使用的页面)。
如果有一个实用程序来“垃圾收集”虚拟文件系统,你可能会再次使用12KB文件。
答案 2 :(得分:0)
每次编译都会创建一个新的不同程序集。
如果您想深入探究究竟有何不同之处,那么您可能需要查看一下这篇文章:“hacking with the clr: diffing assemblies”。
汇编之间不同的事情:
- 时间戳
- 无操作
- ModuleDef GUID
- 调试属性
- 第二时间戳
- PDB-GUID
- 目录差异
- 几个4字节偏移量(DataDirectory.Debug,SizeOFData,AddressOfRawData,PointerToRawData,DataDirectory.MetaData)
我不确定第一次和第二次编译之间的额外2kb大小差异来自何处。但我猜测可能会有一些信息在第一次构建期间未包含但在每次后续编译时都会添加。