c++ - 如何检查可执行文件或 DLL 是在发布还是 Debug模式下构建的 (C++)

标签 c++ dll exe debug-symbols portable-executable

我需要找到模式 EXE/DLL 是在其头文件中构建的。 (仅使用 C++,无需任何外部工具)
有一个关于如何确定 DLL 是在 Release模式还是 Debug模式下构建的旧讨论。
http://forums.codeguru.com/archive/index.php/t-485996.html
但不幸的是,我没有找到任何明确的答案。

最佳答案

I need to find the mode exe/dll was build looking at its headers.



如果“标题”是指 PE 部分或资源(标题不会告诉您任何信息,并且程序通常不随其开发标题一起提供!),那么这是可能的,在限制范围内,并且不可靠。否则,除非您自己编写程序,否则这是完全不可能的努力。

通常,很难以可靠的方式做这样的事情,更何况“调试构建”是 Microsoft Visual Studio 的简化,在大多数编译器下都不存在。例如,对于 GCC,完全允许优化构建但包含调试符号。甚至可以使用 #pragma 打开和关闭优化。 (并更改优化级别甚至目标机器!)从而在未优化的构建中优化功能(或功能组),反之亦然。

调试符号的存在是您对不是您编写的程序的最佳猜测。从生成的二进制文件中判断它是否已被优化是不可能的(无论如何,这并不现实,以一种简单的、自动化的方式)。

栏目 .debug$S.debug$T分别包含调试符号和调试类型。还有一些其他部分以 .debug 开头同样,但它们已被弃用。以“ Debug模式”构建且随后未被剥离的程序将包含部分或全部这些部分。
在不使用外部工具的情况下使用 C++,您将需要跳过 DOS“MZ” stub 和 PE 头文件。在此之后是部分标题,您可以对其进行解析。完整的文件格式文档可以下载here .
最有可能的是,读取文件并为 .debug 进行字符串匹配会一样好。

同样,您可以查看 VERSIONINFO 或 list 文件(它们还允许指定程序是否为调试版本),但这些不是强制性的。您几乎可以在其中写入任何您想要的内容。就目前而言,它们甚至不如查找调试符号可靠。

另一个不可靠的提示是检查程序所链接的系统库的版本。如果是调试版本,则很可能是调试版本。但是,您可以进行发布构建并仍然与调试库链接,没有什么可以阻止您这样做。

下一个最好的猜测是没有调用 CRT assert函数(您可以使用简单的字符串匹配来完成),因为 assert宏(通常从它被调用)在一个构建中完全剥离了 NDEBUG定义。不使用该符号,二进制中不存在字符串。
不幸的是,一个没有任何断言的程序会被错误地识别为“发布版本”,而不管其实际构建如何,并且完全有可能重新定义 assert宏来做一些完全不同的事情(例如 printf 一个文本并继续)。最后,您不知道您链接的某些静态 3rd 方库(显然已经通过了预处理器)是否包含对 assert 的调用。你不知道的。

如果您想检查自己编写的程序,您可以利用优化器将完全删除可证明无法访问或未使用的内容这一事实。可能需要 2-3 次尝试才能使它恰到好处,但基本上它应该像定义一个变量(或导出函数,如果您的编译器/链接器不导出未使用的符号)并编写两三个一样简单无法访问的程序位置的魔法值。优化编译器至少会将这几个多余的 Action 合并为一个,或者更有可能将它们全部消除。
然后,您可以对魔术值进行二进制字符串搜索。如果它们不存在,则它是优化的构建。

关于c++ - 如何检查可执行文件或 DLL 是在发布还是 Debug模式下构建的 (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11115832/

相关文章:

vb6 - 如何重命名 VB6 可执行文件?

text - 在文本编辑器中保存 exe 文件时会发生什么?

c# - 尝试创建与非 .NET 应用程序一起使用的 .NET DLL

c - LoadLibrary 不重用已加载的库

java - 如何从 jar 文件制作 .exe 文件

c++ - 是否可以从 C++ header 构建 Objective-C++ 实现?

visual-c++ - VS 2013 找不到资源编译器DLL。请确保路径正确

c++ - OpenGL GLFW 构建错误或链接错误

c++ - CUDA - 内核调用中的编译错误

c++ - 浮点分辨率似乎比它应该的更受限制