17

使用g ++和-g option,我可以使用gdb进行调试。相当于VS2010 cl编译器的g ++的-g选项?

与Visual Studio 2010 cl.exe编译器的此选项等效的是什么?

这个page有不同的链接库(调试/发布)。

如果我用cl.exe的调试选项进行编译,是否必须使用相应的库链接选项(/ MD/MT vs/MDd/MTd)?

回答

29

这个问题有几个独立的部分:如何告诉编译器/链接器生成并保留“调试信息”(源代码和目标代码之间的映射),如何告诉编译器编译代码的方式不同使调试更简单(考虑assert()和#ifdef _DEBUG),以及链接到项目中的预编译库是否包含调试信息。

-Zi(CL编译器的标志,告诉它产生调试信息)等价于gcc的-g标志。 (还有其他形式的-Z选项:-ZI,如果你想在Visual Studio IDE中使用“编辑和继续”支持,但是如果你使用IDE,你可能使用它的接口编译器设置,而不是直接操纵它们; -Z7如果你想要旧的CodeView格式的调试信息;每当我直接调用CL时,它总是-Zi,我想要。)

请注意,使用-Zi或-ZI)选项通常会为每个目录生成一个.pdb文件,但是当您将代码链接在一起时,它可能来自不同.pdb文件中的.obj文件,并且还希望将这些单独的.pdb文件合并到一个表示你链接在一起的代码的主控制器 - 这是链接器的-debug开关的用途。

另请注意:这可能听起来违反直觉,但始终使用-Zi(对于CL)和-debug(对于link.exe)。即使你将要发布的代码。它不会增加可执行文件的大小,也不会泄露您的客户的秘密,因为调试信息存放在单独的.pdb文件中(您不会将其发送给客户)。如果有任何机会你将不得不去调试它,你会想要.pdb。 (-Zi甚至没有与优化不兼容,虽然-ZI是。所以你可能想用-ZI编译你的“调试”版本,你的“版本”用“-Zi -O2”构建。)

至于库:你不必严格地将C运行库的debug/release属性与代码是否包含调试信息相匹配,但通常是一个好主意 - 如果你要调试你想要的项目能够调试所有它,如果你不打算调试它,你不需要额外的重量。使用给定库的调试/发布版本不会影响它是否有可用的调试符号(希望如果编译库的人理解我在前一段中提到的观点),但它会影响像assert和extra #ifdef _DEBUG该库中的代码。

这适用于您链接的所有库,但特别适用于C运行时库 - Microsoft向malloc()和free()添加了额外的错误检测代码。因此,如果您的项目中有任何内容使用CRT库的调试风格,那么它应该都是。

在我看来,/ M选项(/ MTd和/ MDd)是奇怪而神奇的 - 它们仅仅是一组复杂的其他内容的别名。以/ MDd为例,记录为“定义_DEBUG,_MT和_DLL,并使您的应用程序使用运行时库的调试多线程和DLL特定版本,并使编译器将库名称MSVCRTD。 lib到.obj文件中。“在这里,它影响预处理器(定义_DEBUG和一些其他预处理器符号)和链接器(它实际上将#pragma注释(链接器)放入源代码中)。如果你关心发生了什么并且不理解它,这可能会导致真正的问题 - 我已经看到许多不使用IDE的项目陷入了关于msvcrt.lib和msvcrtd.lib的警告中。被链接等等。当你理解如何安全地使用这些(/ M选项)时,你不再需要它们了!我更喜欢将事情明确化:直接在需要的地方指定“-D _DEBUG”,指定明确链接哪些库(并使用-nodefaultlib),然后不需要/ M选项。

+4

+1哇。我可能会问你是如何变得熟悉微软工具链的特质的? :) – 2011-01-11 23:39:37

6

您正在查找debug information generation options/Z7,/Zi/ZI)之一。

如果您使用其中之一,则还应将/DEBUG选项传递给链接器。

您还需要链接运行时库(/MDd/MTd)的debug version。这一点很重要,因为这些版本与其版本对应版本不同(例如,它们的内存分配例程不兼容)。