编译后的C ++二进制文件存储原始源代码吗?

时间:2014-11-19 11:53:12

标签: c++

当我运行一些C ++代码并且收到错误时,它设法打印出发生该错误的特定源文件中的确切行。这显然很适合调试,但我相信我运行的程序是在发布模式下构建的。所以我的问题是,所有以发布模式构建的程序都存储原始的源c ++代码,并在编译的二进制文件中引用它吗?如果只是将二进制文件分发给消费者而不是开发人员,这似乎是一种创建二进制文件的低效方法。

3 个答案:

答案 0 :(得分:3)

我从未见过“主流”C ++编译器存储原始源代码。当您看到对源的一些引用时,通常归结为其中一个技巧:

  • 对源文件/行的引用:这些是通过宏创建的。大多数日志库提供了一些宏,其中包含__FILE____LINE__宏,其中,在编译时,扩展到当前文件和行;像__FUNCTION__这样的宏是常见的扩展名;
  • 失败断言中的
  • 表达式:assert宏(和类似的野兽)通常不仅使用__FILE____LINE__,而且还将(在编译时)在给定表达式中字符串化为在assert失败时显示;
  • 可执行文件中的类名称:如果启用RTTI,编译器必须存储类型名称的某处,以允许使用typeid运算符;
  • 您在调试器/堆栈跟踪中看到的内容:这来自调试信息,它允许从指令指针到源中的位置和函数名称的反向映射;这当然需要调试信息(可能在发布版本中生成,也可能不生成,或者可能放在单独的文件中)和实际源(如果您想查找代码实际上是什么)。

    由于这两者都很大(在我所处理的项目中,它是剥离的可执行文件大小的12倍)并且可以帮助进行逆向工程,因此很少发送给客户(但是保留在内部,是能够分析已发布应用程序生成的“原始”堆栈跟踪。

答案 1 :(得分:2)

没有。在调试和发布模式下都不存储实际的源。 工具链可以存储足够的信息以供调试器映射 机器代码中的地址到源中的行,但来源 如果调试器要显示任何内容,则必须可用。这有 与“调试”或“释放”模式无关;至少在我们的 配置,我们将它存储在两者中。 (当然,因为编译器 可能会在优化时重新排列代码位,而信息则不会 总是可以在优化的构建中利用。)

至于assert的输出:C ++有两个内置宏,__FILE____LINE__,编译器将用适当的替换 编译代码时的值。这些用于assert 宏(通常至少),通常在各种用户定义的日志记录中 宏也是。宏预处理器还有一个运算符 “stringize”其参数,可用于获取断言 将表达式转换为断言输出。

答案 2 :(得分:0)

编译器不存储原始源代码。如上所述,通过调试构建,它们存储用于引用源代码的行号。有一些旧的工具集(汇编程序,编译器)会将源代码的片段留在程序中应该是未初始化的内存中,只是抓住在汇编或编译时在内存中发生的任何事情,当创建未初始化的内存区域时程序。这主要发生在.COM程序文件中,因为没有提供未初始化内存的加载时间分配,因为有.EXE程序。