Visual Stdio C++ Debug 信息

当我们采用一个调试器调试一个应用程序时,我们总是希望能单步跟踪代码、设置断点、查看变量值,哪怕变量是自定义的用户类型。但是对于一个EXE程序来说,基本上就是一堆二进制数据(目前的WindowsEXE程序中还包含了一些头部信息,用于系统执行程序)。当一个EXE程序运行时,系统将为这些EXE分配一些额外的内存用于存储运行时数据(StackHeap)。但是依旧没有任何调试方面的信息。当程序Coredump时,像WinDBG这些调试器是如何定位到哪一行的呢,这些都是Visual Studio中的一些编译特性。

调试信息种类

Intel X86指令体系下的Windows平台,一个EXE或者DLL中主要有下面几种调试信息:

Debug类型

说明

Public functions and variables

主要包括了一些全局变量和全局函数信息。在Debug信息中主要存储了他们的位置、大小、名字信息

Private functions and variables

主要包含了非全局的变量和函数信息。

Source File and  Line Information

主要包含了每一行代码在EXE中的对应位置信息

Type Information

主要存储了各种数据类型信息,包括用户自定义的数据类型

FPO Information

FPO(Frame Pointer Omission)Frame Pointer 是一种用来在调用堆栈(Call stack)中找到下一个将要被调用的函数的数据结构源代码的行序号(Source-line numbers;编译器可针对这一特性做优化,Debug信息中依旧可以存储一些信息,用来查询函数的栈区帧大小信息。

Edit and Continue Information

主要包含了要实现用户编辑后可以继续执行特性的相关信息。

1 Windows平台下调试信息分类


调试文件格式分类
在过去二十多年的时间里,微软采用了三种形式来存储DEBUG信息:COFF,CodeView,Program Database。我们从三个维度来对比分析一下这三种格式:
1.
每种格式中存储了哪些调试信息?
2.
每种格式的调试信息存储在哪里?(包含在EXE中还是单独的调试信息文件)
3.
每种格式的设计文档是否齐全?

COFF

这是最老的一种格式,只能存储三种信息:Public functions and variables, source file and line information, FPO信息。COFF信息是存储在EXE文件中的,不能单独存储。这种格式文档有详细的说明: Microsoft Portable Executable and Common Object File Format Specification

CodeView

这是在COFF基础上推出的一个更为复杂一些的格式。它可以存储表1中除了Edit and Continue Information外的其他信息。CodeView信息通常存储在EXE文件中,但是它也可以存储在单独的文件(.DBG)中。CodeView的格式文档在MSDN上有部分说明,不是很齐全。

Program Database

这是微软最新的格式。他可以存储表1中所有信息。另外,他还存储了增量链接(increase Linking)信息。这在其他格式中不可能存在的。
Program Database
格式信息通常存储在单独的文件(.PDB)中。
Program Database
格式微软并没有提供格式文档说明。但是微软提供了两套SDK接口:DBGHelpDIA供用户调用。PDB有两个版本,一个是PDB 2.0, 主要在VS6.0中使用。一个是PDB7.0,主要用在Visual Studio.NET之后的版本。DBGHelp是普通的API接口。而DIA提供的是COM接口。相对来说DBGHelp使用起来相对简单一些,但是DIA提供的信息相对丰富一些。
下表是三种格式的对比:

格式

文档齐全度

存储

public function and variables

Type information

FPO information

EnC information

COFF

齐全

EXE

+

-

+

-

CodeView

部分

EXE或者单独文件(.DBG)

+

+

+

-

Program Database

单独文件(.PDB)

+

+

+

+

2:三种不同格式的对比

如何产生调试信息

Windows下,一个EXE典型的生成过程主要分为两步:编译(Compile)和链接(Link),可以用下图来描述:

 clip_image001

如果我们想产生DEBUG信息,同样需要分为两步:我们要求编译器(Compiler)为每一个源文件产生相应的调试信息文件;然后由链接器(Linker)把各个调试文件合并成一个大的调试文件。可以用下图来描述:

 clip_image002

在缺省情况下,编译器和链接器不会产生调试信息,我们需要在编译和链接选项中设置参数,告诉编译器和链接器我们需要生成DEBUG信息、生成什么格式的调试信息、调试信息存储在哪里等。
下面我们按照Visual C++6.0Visual C++.NET两种不同版本的IDE分别介绍。

Visual C++ 6.0

编译器选项

主要包含了下面几个选项:
/Zd 产生COFF格式调试信息,并保存在目标文件中。
/Z7
产生CodeView格式调试信息,并保证在目标文件中。
/Zi
产生Program Database格式调试信息,并单独存储在.PDB文件中。
/ZI
Zi类似。并在Zi基础上增加了Edit and Continue信息。

选项

格式

存储格式

包含内容

/Zd

COFF

.obj

·                Public functions and variables

·                Source file and line information

·                FPO information

/Z7

CodeView

.obj

·                Public functions and variables

·                Private functions and variables

·                Source file and line information

·                Type information

·                FPO information

/Zi

Program Database

.PDB

·                Public functions and variables

·                Private functions and variables

·                Source file and line information

·                Type information

·                FPO information

/ZI

Program Database

.PDB

·                Public functions and variables

·                Private functions and variables

·                Source file and line information

·                Type information

·                FPO information

·                Edit and Continue data

链接器选项

主要包含了一下链接选项:

/debug 告诉Linker产生调试信息,如果该选项未设置,其它选项设置都不起作用。

/debugtype 告诉Linker采用哪个格式的调试信息,主要包含了下面几种:/debugtype:coff COFF格式; /debugtype:cv CodeView或者Program Database格式(依赖 /pdb 选项) /debugtype:both 同时产生COFFCodeView/Program Database信息。

/pdb 告诉Linker到底采用CodeView还是Program Database格式. /pdb:none 告诉Linker采用CodeView格式, /pdb:filename 告诉linker采用Program Database格式而且制定了PDB文件的名字.如果debugtype:coff 选项设置了, /pdb 选项不起作用.

/pdbtype选项主要用在有多个文件需要链接时,告诉链接器如何处理各个文件的调试信息。/pdbtype:sept表示Linker不会将各个文件的PDB文件合并到最后一个PDB文件中。如果要调试,需要准备各个PDB文件,而/pdbtype:con选项就是将各个PDB文件合并到一个PDB文件中。

/debugtype

/pdb

格式

存储

coff

无作用

COFF

EXE

coff

无作用

COFF

EXE

cv

/pdb:none

CodeView

EXE

cv

/pdb:filename

Program Database

.PDB

both

/pdb:none

COFF and CodeView

EXE

both

/pdb:filename

COFF and Program Database

COFF信息存储在EXE中,Program Database存储在单独PDB文件中

3 不同的Linker选项

Visual C++ 2002,2003,2005

编译器选项

主要包含了/Zd, /Z7, /Zi, /ZI。但是/Zd已经在Visual C++ 2005中不被支持了。

clip_image003

链接器选项

主要包含三个选项:
/debug 告诉Linker产生调试信息,如果该选项未设置,其它选项设置都不起作用。
/pdbfilename 告诉linker采用Program Database格式而且制定了PDB文件的名字.
/pdbstripped
告诉Linker产生单独的PDB文件,只包含两种信息:public functions and variables;FPO information.
Visual C++.NET中,Linker已经不支持COFFCODEVIEW两种格式了。

 静态库的调试信息

由于静态库不需要Linker,因此静态库的调试信息相对来说就简单多了,设置/Z*Z7,Zd,Zi,ZI)选项就可以产生相应的调试信息。
对于Z7Zd选项,调试信息存储在相应的.lib文件中,而ZiZI选项,调试信息存储在独立的.PDB文件中。

调试信息和可执行文件大小关系

调试信息是否影响最终EXE文件的大小,依赖于调试信息存储的地方,说到底依赖于我们选择的格式。
当采用COFFCodeView方式时,通常调试信息存储在EXE文件中,将会导致EXE文件极度膨胀,基本上会翻倍。
当采用Program Database方式时,EXE文件就几乎不受影响了。EXE文件仅仅增加了几百个字节的头域,用于定位相应的PDB文件信息。

选项

格式

存储

内容

/Z7

CodeView

.OBJ

·                Public functions and variables

·                Private functions and variables

·                Source file and line information

·                Type information

·                FPO information

/Zi

Program Database

.PDB

·                Public functions and variables

·                Private functions and variables

·                Source file and line information

·                Type information

·                FPO information

/ZI

Program Database

.PDB

·                Public functions and variables

·                Private functions and variables

·                Source file and line information

·                Type information

·                FPO information

·                Edit and Continue data

4Visual C++.NET下的编译选项

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值