(这是关于 gcc 和 clang 的问题,但可能适用于其他编译器。)
如果我编译我的 C 或 C++ 代码,并使用-g
开关生成调试信息,这本身是否会以任何方式降低已编译程序的性能......
- 使用最小优化 (
-O0
)? - 最大优化 (
-O3
)?
注意:我并不是指必须解析/加载可执行文件的性能损失,由于额外的内容,性能损失更大;我的意思是运行的代码。
(这是关于 gcc 和 clang 的问题,但可能适用于其他编译器。)
如果我编译我的 C 或 C++ 代码,并使用-g
开关生成调试信息,这本身是否会以任何方式降低已编译程序的性能......
-O0
)?-O3
)?注意:我并不是指必须解析/加载可执行文件的性能损失,由于额外的内容,性能损失更大;我的意思是运行的代码。
我不认为有任何性能差异。实际上,生成的代码将是相同的,并且-g
可以-O
根据此处的文档使用。此外,调试符号不会写入代码,而是写入另一个称为“调试部分”的部分,该部分甚至不会在运行时加载(仅由调试器加载)
-g
不会改变运行的优化或生成的代码。这是此处所述的 gcc 政策
但是,请注意相同的文档指出:
优化代码所采用的捷径有时可能会令人惊讶:您声明的某些变量可能根本不存在;控制流可能会短暂地移动到您没有预料到的地方;有些语句可能无法执行,因为它们计算常量结果或它们的值已经在手边;有些语句可能会在不同的地方执行,因为它们已移出循环。尽管如此,还是可以调试优化的输出。这使得将优化器用于可能有错误的程序是合理的。
因此,最终调试永远不会损害您的优化,但相反是错误的,并且使用-O3
可能会降低您的调试信息(例如通过删除无用的变量)。
请注意,在这种情况下使用-Og
(如此处所述)可能会更好,因为它会:
优化调试体验。-Og 启用不干扰调试的优化。它应该是标准编辑-编译-调试周期的首选优化级别,提供合理的优化级别,同时保持快速编译和良好的调试体验。
但是,这会影响性能,因为不会完成一些会干扰调试的优化过程。
编辑:
链接和引号回答了您的问题。gcc
它可能不适用于其他编译器,例如clang
. 但是,我也找到了一些文档clang
。例如这里:
基本上,调试信息允许您使用“-O0 -g”编译程序并获得完整的调试信息,允许您在程序从调试器执行时任意修改程序。使用“-O3 -g”编译程序会为您提供始终可用且准确的完整调试信息(例如,尽管消除了尾调用和内联,但您可以获得准确的堆栈跟踪),但您可能会失去修改程序的能力和调用在程序外优化或完全内联的函数。
-g 标志将调试信息添加到二进制文件。这存在于与CPU 运行位不同的可执行文件部分 (.stab
和) 中。在调试器外部运行时,操作系统加载程序不会加载调试部分。调试信息也可以使用该实用程序轻松删除,以生成与未使用 -g 标志编译的二进制文件相同的二进制文件。.stabstr
.text
strip
但是,通常当您想要调试东西时,您将在没有优化和 NDEBUG 预处理器宏的情况下进行编译。然而,这些东西不受 -g 标志的控制。
如果您在调试器之外运行它,不会对性能造成任何影响。调试符号是为了帮助调试。在这两种情况下生成的代码应该是相同的。