GCC和G++的区别、使用、优化方式、gprof工具和gcov工具

GCC 和 G++ 简介

GCC(GNU Compiler Collection)和 G++ 是开源的编译工具,广泛用于 C、C++ 等多种编程语言的编译和构建。它们是 GNU 项目的一部分,支持多种平台。


1. GCC 和 G++ 的区别

特性GCCG++
主要用途编译 C 代码和其他语言(如 Fortran、Ada)。专门用于编译 C++ 代码。
默认语言默认编译器为 C。默认编译器为 C++。
调用方式手动指定 gcc 支持的语言。自动将输入文件识别为 C++。
链接行为默认使用 C 的标准库 libc自动链接 C++ 的标准库 libstdc++

2. GCC

功能

  • 多语言支持:可以编译 C、C++、Fortran、Ada、Go 等多种语言。
  • 通用性:作为一组编译工具的核心,提供灵活的选项和多阶段优化。
  • 跨平台性:支持多种操作系统和架构。

示例

编译 C 程序:

gcc -Wall main.c -o main //注意加上-Wall可以更好的检查一些错误警告

手动编译 C++ 程序(但需要显式链接 C++ 标准库):

gcc -Wall main.cpp -lstdc++ -o main

3. G++

功能

  • 专为 C++ 语言设计。
  • 自动链接 C++ 标准库(libstdc++),无需显式指定。
  • 默认开启 C++ 标准支持,支持现代 C++ 标准(如 C++11、C++17、C++20)。

示例

编译 C++ 程序:

g++ -Wall main.cpp -o main

支持不同的 C++ 标准:

g++ -std=c++17 main.cpp -o main

4. GCC 和 G++ 的关系

  • 底层一致性:GCC 和 G++ 使用的是同一个编译器核心,G++ 是 GCC 的一个专门用于 C++ 的包装。
  • 差异在于默认行为:GCC 默认处理 C 代码,而 G++ 自动启用 C++ 编译器及标准库支持。

5. 常见选项

无论是 GCC 还是 G++,它们支持许多相同的编译选项,例如:

  • -c:只编译,不链接。
  • -o:指定输出文件名。
  • -Wall:启用所有常见警告。
  • -g:生成调试信息。
  • -O2:启用优化。

6.优化方式

在编译器优化中,CSE(Common Subexpression Elimination)和 FL(Function Inlining)是常见的优化技术,它们可以提高代码的执行效率和运行速度。以下是对两者的简单介绍:

CSE:公共子表达式消除(Common Subexpression Elimination)

定义

公共子表达式消除是一种通过减少重复计算来优化代码的技术。它检测程序中出现的相同子表达式,并将其替换为单次计算结果的引用,从而节省重复计算的开销。

优化示例

未优化的代码:

int a = (x + y) * (x + y);

在该代码中,(x + y) 是一个公共子表达式。

优化后的代码:

int t = x + y;
int a = t * t;
优点
  • 减少重复计算,提高执行效率。
  • 节省 CPU 时间。
限制
  • 增加了临时变量的使用,可能稍微增加内存消耗。
  • 需要编译器静态分析以确保子表达式没有副作用(如函数调用或全局变量修改)。

FL:函数内联(Function Inlining)

定义

函数内联是通过将函数调用替换为函数体的方式来消除函数调用的开销。它直接将被调用的函数代码插入调用点,从而减少函数调用的开销。

优化示例

未优化的代码:

int square(int x) {
    return x * x;
}

int main() {
    int result = square(5);
    return result;
}

优化后的代码(内联展开):

int main() {
    int result = 5 * 5; // 函数调用被直接替换为函数体
    return result;
}
优点
  • 减少函数调用的开销(如参数传递和栈操作)。
  • 可能进一步触发其他优化(如循环展开或常量传播)。
限制
  • 内联会增加代码体积(代码膨胀),尤其是频繁调用的大函数。
  • 对递归函数无效,通常不会内联递归调用。

CSE 和 FL 的对比

特性CSEFL
全称Common Subexpression EliminationFunction Inlining
作用对象表达式函数调用
优化目标减少重复计算,节省时间消除函数调用开销,提高性能
可能的副作用增加临时变量数量增加代码体积
适用场景表达式中存在重复计算函数调用频繁且函数体较小

总结

  • CSE(公共子表达式消除):针对代码中的重复表达式优化,减少计算次数。

  • FL(函数内联):针对函数调用优化,减少调用开销。

    • 编译器通常会根据代码的复杂性、函数体大小和优化级别(如 -O1-O2-O3)自动应用这些技术,而开发者也可以通过写高效代码配合编译器的优化策略。
    • 使用gcc -Wall -O2 -c hello.c得到的文件hello.o,大小不一定比-O1的优化要小,有可能会大于O1优化的代码,并且运行时间也有可能会比-O1的时间长。

7.gprof工具和gcov工具

gprofgcov 是 GNU 工具链中的两个分析工具,分别用于 性能分析代码覆盖率分析。以下是它们的详细用法和区别:

gprof:性能分析工具

作用

gprof 用于分析程序的性能,提供以下信息:

  • 程序运行过程中函数调用的次数。
  • 每个函数执行的总时间和调用次数分布。
  • 调用图信息(函数之间的调用关系)。
使用步骤
  1. 编译程序(启用性能分析)
    使用 -pg 选项编译和链接程序:

    gcc -pg program.c -o program
    
  2. 运行程序
    执行编译生成的程序,会生成性能数据文件(gmon.out):

    ./program
    
  3. 生成性能分析报告
    使用 gprof 命令分析 gmon.out 文件,输出报告:

    gprof program gmon.out > report.txt
    
  4. 查看分析结果
    打开 report.txt,可以看到以下信息:

    • Flat Profile:每个函数的执行时间和调用次数。
    • Call Graph:函数之间的调用关系及时间分布。
示例输出
Flat profile:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds    seconds  calls   ms/call  ms/call  name
 50.0      0.50     0.50       2   250.00   250.00   foo
 50.0      1.00     0.50       1   500.00   500.00   bar
  • foobar 是函数名称。
  • calls 是函数调用次数。
  • self seconds 是该函数本身运行所花费的时间。

gcov:代码覆盖率工具

作用

gcov 用于检测程序的代码覆盖率,帮助开发者了解:

  • 哪些代码被执行了。
  • 哪些代码未被执行(死代码)。
  • 每行代码的执行次数。
使用步骤
  1. 编译程序(启用覆盖率分析)
    使用 -fprofile-arcs-ftest-coverage 选项编译程序:

    gcc -fprofile-arcs -ftest-coverage program.c -o program
    
  2. 运行程序
    执行编译生成的程序,会生成以下文件:

    • program.gcda:覆盖率统计数据文件。
    • program.gcno:源代码结构文件。
    ./program
    
  3. 生成覆盖率报告
    使用 gcov 生成覆盖率报告:

    gcov program.c
    

    会生成一个 program.c.gcov 文件,包含每行代码的执行次数信息。

  4. 查看覆盖率报告
    打开 program.c.gcov 文件,可以看到每行代码的覆盖信息:

          -:    0:Source:program.c
          -:    1:#include <stdio.h>
          -:    2:
          1:    3:int main() {
          1:    4:    printf("Hello, World!\n");
          1:    5:    return 0;
          -:    6:}
    
    • 1: 表示该行代码被执行 1 次。
    • -: 表示该行是注释或不可执行代码。
    • #####: 表示该行从未被执行。
    • 可以使用grep "#####" *.gcov 查看没有被执行的代码。

覆盖率百分比

可以结合 lcov 工具生成 HTML 格式的覆盖率报告,方便查看总覆盖率。


gprof 和 gcov 的对比

特性gprofgcov
主要用途性能分析:关注函数运行时间和调用次数覆盖率分析:关注代码的执行情况
输出内容函数调用图,执行时间分布每行代码的执行次数及覆盖率信息
适用场景优化程序性能找出未被测试的代码
生成文件gmon.out 文件.gcda.gcno 文件
编译选项-pg-fprofile-arcs -ftest-coverage

总结
  • 使用 gprof 优化程序的性能瓶颈,关注函数的时间和调用关系。
  • 使用 gcov 确保代码的测试覆盖率,查找未被执行的代码部分。
  • 两者可以结合使用,优化程序的性能和质量。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值