GCC是否会优化空方法调用?如何查看编译输出中的方法与字段?
问题与优化咨询
现有代码
bool OutputNewline = true; void Output(std::string str, bool newLine = true) { if (!OutputNewline) { putchar('\n'); OutputNewline = true; } if (str.length() == 0) { return; } fputs(str.c_str(), stdout); fflush(stdout); OutputNewline = (str[str.length()-1] == '\n'); } void OutputDebug(std::string str, bool newLine = true) { #if defined(DEBUG) && DEBUG == true Output(str, newLine); #endif }
疑问点
- 未开启
DEBUG宏时,OutputDebug是否会产生无意义的空调用?有没有更优实现方式? - 在g++ 12.2.0、Debian GNU/Linux 12环境下,如何查看编译输出文件中实际包含的方法与字段?
解答
关于OutputDebug的优化
当前写法在未定义DEBUG或DEBUG!=true时,编译器会把OutputDebug的函数体完全剔除,但参数表达式的求值不会被跳过。比如调用OutputDebug(generate_log_string())时,哪怕DEBUG未开启,generate_log_string()仍然会执行,这会造成不必要的性能损耗。
更优的实现是用宏替代函数,这样在非调试模式下,整个调用语句都会被预处理器移除,连参数都不会求值:
#if defined(DEBUG) && DEBUG == true #define OutputDebug(str, newLine) Output(str, newLine) #else #define OutputDebug(str, newLine) ((void)0) #endif
这样在非调试模式下,所有OutputDebug调用都会被替换为空语句,完全不会产生任何运行时开销。
另外,原Output函数的参数std::string str是值传递,每次调用都会拷贝字符串,建议改成const std::string& str引用传递,减少不必要的内存拷贝,提升性能:
void Output(const std::string& str, bool newLine = true) { // 原逻辑不变 }
查看编译输出文件的方法
在g++ 12.2.0、Debian 12环境下,常用以下工具查看编译后文件的符号(方法、字段等):
- nm命令:查看目标文件或可执行文件的符号表,加上
-C参数可以还原C++名字修饰后的原名:
如果是动态库,用nm -C ./your_executablenm -D ./your_shared_lib.so查看动态符号。 - objdump命令:可以反汇编文件并显示符号信息,
-C解修饰,-D全量反汇编:
用objdump -CD ./your_executable-t参数可以只看符号表:objdump -Ct ./your_executable。 - readelf命令:专门处理ELF格式文件,
-s查看符号表,-a查看全部文件信息:readelf -s ./your_executable
这些工具可以直接看到编译后实际保留的方法、全局变量等符号,确认OutputDebug是否在非调试模式下被完全移除。
内容的提问来源于stack exchange,提问作者Jay Dee
相关产品推荐
相关产品推荐

