GCC 4.8:-Og是否意味着-g?

36
最近,GCC 4.8 的文档进行了更新,引入了一个新的优化开关:-Og。这个开关可以在提供合理运行时性能的同时,解决快速编译和卓越调试体验的问题。总体来说,使用该开关进行开发应该比默认的优化级别 -O0 更好。那么这个开关是否意味着-g,还是我需要手动添加到我的CXXFLAGS中?

8
显然,“注意-Og不意味着-g,它只是禁用可能干扰调试的优化。”- Gentoo wiki - Marco Scannadinari
有些东西可以证明这两个陈述中的任何一个,也许是一些来自gcc的代码摘录?如果发布为答案,我会接受并点赞它。 - cschwan
3个回答

45

查看GCC 4.9.2源代码(gcc/opts.c),发现-Og-O1相同,但禁用了一些标志,可能会导致更糟糕的调试体验:

/* in function default_options_optimization: */
    case OPT_Og:
      /* -Og selects optimization level 1.  */
      opts->x_optimize_size = 0;
      opts->x_optimize = 1;
      opts->x_optimize_fast = 0;
      opts->x_optimize_debug = 1;
      break;
几步之后,函数maybe_default_option被调用,其参数为一组选项和标志x_optimize_debug。当使用-Og时,带有OPT_LEVELS_1_PLUS_NOT_DEBUGOPT_LEVELS_1_PLUS_SPEED_ONLYOPT_LEVELS_2_PLUS_SPEED_ONLY标记的选项将不会被启用。
所以这就是“应该比-O0更好”的说法的来源。 -Og介于-O0-O1之间。这不影响通过-g选项启用的调试信息的包含。您可能还对不同的-g选项感兴趣:
  • 选项-ggdb覆盖-g。也就是说,如果在-g之后设置了-ggdb,则实际上会忽略-g选项。
  • 选项-g等同于-g2,省略-g相当于-g0
  • 选项-g3产生比-g2更大的调试部分,-ggdb3也是如此。
  • 更高的优化级别都会导致代码和调试部分增加。 (-O0 < -O1 < -Og < -O2 < -O3)。
  • strip --strip-debug的对象大小与-g级别无关。这符合只有-O级别对实际代码产生影响的预期,其中-g确定调试部分。
  • strip --keep-debug导致对象的大小由-g级别主导,其次是-O级别。(因此-g0 -O3-g3 -O0小)。

注意:我没有考虑编译时间。随着更积极的优化级别,编译时间可能会增加。我希望调试级别对时间的影响很小(与优化相比),因为这只意味着需要在处理过程中跟踪额外的细节。

下面是我用来测试实际行为的命令(也将-gX-ggdbX进行比较):

for g in -g0 -g2 -g3;do
    for O in -O0 -O1 -O2 -O3 -Og; do
        flags="$g $O";
        gcc -fPIC -rdynamic -c -Wall -Wextra -Ilib ltunify.c -o obj/gL_"${flags// /_}_.o" $flags || break;
    done;
done

26

简短回答: 不,您仍需要手动添加-g

详细回答:

我曾尝试从最初的来源中找到一个确切的答案,但没有找到,所以我决定按照这里描述的方法进行测试:如何检查程序是否使用调试符号编译?

我使用-O3标志构建了一个可执行文件,而没有使用-g。使用命令objdump --syms <file> | grep debug并没有产生任何结果,这是预期的。

然后,我使用-g标志构建了一个可执行文件,而没有使用任何优化标志。同样的objdump命令产生了六个类似于以下内容的结果:

0000000000000000 l d .debug_info 0000000000000000 .debug_info

最后,我使用-Og标志构建了一个可执行文件,而没有使用-g。该objdump命令没有产生任何结果。这意味着在这种情况下不存在调试符号。

虽然我找不到来自GCC本身的明确文档,但Gentoo Wiki(如Marco Scannadinari之前提到的)确认了我的断言,即-Og不意味着-g


1

gcc手册 --version gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2) 在fedora 29 workstation x86_64上。

版本不同,但我认为这很有帮助。

Options for Debugging Your Program

...
  If you are not using some other optimization option, consider using -Og with -g.  With no -O option at
  all, some compiler passes that collect information useful for debugging do not run at all, so that -Og may
  result in a better debugging experience.
...

Options That Control Optimization

...
  -Og Optimize debugging experience.  -Og enables optimizations that do not interfere with debugging. It
      should be the optimization level of choice for the standard edit-compile-debug cycle, offering a
      reasonable level of optimization while maintaining fast compilation and a good debugging experience.
...

因此,我们可以看到-Og是优化选项之一。如果您没有使用其他优化选项,请考虑在-g与-Og一起使用。

示例:

#include <stdio.h>

int main(int argc, char *argv[]) {
    int n;

    for (n=0; n<10; n++) {
       printf("Print Number: %d\n", n);
    }
    return 0;
}

编译:
[user@localhost myctest]$ gcc sample.c -o sample
[user@localhost myctest]$ gcc sample.c -o sample.Og -Og
[user@localhost myctest]$ gcc sample.c -o sample.g -g
[user@localhost myctest]$ gcc sample.c -o sample.Og.g -Og -g

然后你可以看到编译后文件的大小:
[user@localhost myctest]$ ls -l --human-readable sample*
-rwxrwxr-x. 1 user user 18K Aug 10 19:43 sample
-rw-rw-r--. 1 user user 162 Aug 10 19:43 sample.c
-rwxrwxr-x. 1 user user 21K Aug 10 19:43 sample.g
-rwxrwxr-x. 1 user user 18K Aug 10 19:43 sample.Og
-rwxrwxr-x. 1 user user 21K Aug 10 19:44 sample.Og.g

然后您可以使用readelf(GNU readelf版本2.31.1-13.fc29)重新检查这些文件中的调试信息。

[user@localhost myctest]$ readelf --debug-dump=aranges sample
[user@localhost myctest]$ readelf --debug-dump=aranges sample.g
Contents of the .debug_aranges section:

  Length:                   44
  Version:                  2
  Offset into .debug_info:  0x0
  Pointer Size:             8
  Segment Size:             0

    Address            Length
    0000000000401126 000000000000003d 
    0000000000000000 0000000000000000 

[user@localhost myctest]$ readelf --debug-dump=aranges sample.Og
[user@localhost myctest]$ readelf --debug-dump=aranges sample.Og.g
Contents of the .debug_aranges section:

  Length:                   44
  Version:                  2
  Offset into .debug_info:  0x0
  Pointer Size:             8
  Segment Size:             0

    Address            Length
    0000000000401126 0000000000000028 
    0000000000000000 0000000000000000 
 

您可以通过使用-Og选项编译的文件中看不到调试信息。您也可以使用readelf --debug-dump=选项检查更多信息。例如:readelf --debug-dump=aranges,info sample.greadelf --headers sample.g | grep debug

请参阅man readelf

--debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]

您可以使用gdb进行检查:

[user@localhost myctest]$ gdb sample.Og
GNU gdb (GDB) Fedora 8.2-3.fc29
Copyright (C) 2018 Free Software Foundation, Inc.
...

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from sample.Og...(no debugging symbols found)...done.
(gdb) 

然后您会得到文件 sample.Og(未找到调试符号)

4.8.x

针对4.8.x文档,调试选项部分没有提到-Og,仅在优化选项部分中介绍。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接