把GCC的编译信息重定向到一个文件

本文介绍了在Linux环境下,如何将编译时产生的错误信息重定向到特定文件中,以便于调试和错误定位。通过使用特殊的重定向符号,可以有效地解决错误信息显示不全的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在Linux下进行编程,很多写好的代码要进行编译。在链接很多文件的时候,经常会出现很多的错误,而Linux下终端显示是有限的,因此每次调试的时候如果错误太多就会很不方便。如果使用简单的管道重定向如下:
gcc -c test.c > error.txt
这种方式是不行的。
 
我上网找相关的方法,发现很多人在问,找到的信息也比较少。有些方法甚至要写程序截获Linux的管道输出流,真是麻烦。
 
功夫不负有心人,我找到了一种简单的方法,其实道理很简单,就是Unix下错误输出的ID一般为2,那么我们在重定向的时候,重定向符号改为2>就可以了,如下所示:
gcc -c test.c 2> error.txt
 
另外,>和>>重定向是有一定区别的,>>是追加在指定的输出后面。
<think>我们正在处理一个关于GCC编译生成map文件缺少size统计信息的问题。根据用户描述,生成的map文件缺少size统计信息,这可能是为了优化或调试目的需要的。首先,我们需要了解GCC生成map文件的相关选项。在GCC中,生成map文件的选项是`-Wl,-Map=output.map`,它通过链接器选项来生成map文件。但是标准的map文件可能并不包含每个函数或变量的size信息,它主要包含地址分配、符号地址、库依赖等信息。如果用户需要size信息,通常我们可能需要使用其他工具来获取,比如`size`命令、`nm`命令或者`objdump`命令。但是,用户希望直接在map文件中包含这些信息,所以我们需要寻找在GCC链接阶段生成包含size信息的map文件的方法。查阅GCC和ld的文档,我们发现标准的链接器生成的map文件并不包含每个符号的size。然而,我们可以通过链接器脚本或者使用其他工具来增强map文件的内容。另外,我们可以考虑使用`-Wl,--print-memory-usage`选项来在链接时输出内存使用情况,但这可能不会输出每个符号的size。另一种方法是使用`nm`工具来生成包含size的符号表,然后将其与map文件合并。但是,这需要在编译后额外执行步骤。但是,我们注意到在GCC中有一个`-fprint-stats`选项?实际上,这个选项是用于编译时统计信息的,而不是链接时的。经过进一步思考,我们可以尝试使用链接器脚本中的`SIZEOF`命令?但是链接器脚本主要用于控制内存布局,并不直接输出size信息到map文件。实际上,GNUld链接器在生成map文件时,可以通过`--cref`选项添加交叉引用信息,但这也不包含size。那么,有没有办法让ld输出每个符号的size到map文件呢?查阅ld的文档,我们发现ld有一个选项`--print-symbol-sizes`,它可以打印每个符号的大小。我们可以尝试将这个选项传递给链接器。具体做法是:在GCC命令行中,通过`-Wl`选项将这个选项传递给链接器。例如:```gcc...-Wl,-Map=output.map-Wl,--print-symbol-sizes...```但是,请注意,`--print-symbol-sizes`选项会将符号大小输出到标准错误(stderr),而不是直接写入map文件。因此,我们需要将标准错误重定向文件,然后合并到map文件中。或者,我们可以使用链接器脚本或其他方法。另一种方法是,使用`-Wl,--trace-symbol=symbol_name`可以输出特定符号的信息,包括大小,但这样需要指定符号,不适合所有符号。实际上,我们可以这样操作:1.正常编译并生成map文件(使用`-Wl,-Map=output.map`)。2.使用`nm--size-sort`命令来获取每个符号的大小,并生成一个符号大小列表。3.将符号大小列表与map文件合并。但是,用户希望一步到位在map文件中包含size信息。经过更深入的查找,我们发现ld并没有直接提供将符号大小写入map文件的选项。因此,可能需要使用后处理脚本。但是,我们也可以尝试通过修改链接器脚本,在map文件中输出section的大小,但这并不能精确到每个函数或变量。因此,我们可能需要接受一个事实:标准的map文件不包含每个符号的大小,我们需要使用其他工具来获取。不过,我们可以考虑使用`objcopy`工具来生成一个包含符号大小的文件,然后与map文件合并。然而,根据用户的需求,我们也可以推荐使用`nm`工具来获取符号大小。例如:```nm--size-sortyour_executable```或者使用`objdump`:```objdump-t--section-headersyour_executable```但是,用户明确提到是在map文件中缺少size统计信息,所以我们需要在生成map文件的同时包含这些信息。我们注意到,在GCC的选项中,有一个`-fstack-usage`选项,它会为每个函数生成堆栈使用信息,但这并不是符号大小。还有一种方法是使用`-Wl,--stats`,它会输出内存使用统计,但不包括每个符号的大小。因此,我们可能需要采取折中方案:在链接时同时生成map文件和符号大小文件,然后合并。具体步骤如下:1.编译并链接时,生成map文件:```gcc-ooutput...-Wl,-Map=output.map```2.使用nm命令生成符号大小信息:```nm--print-size--numeric-sortoutput>output.sizes```3.将output.sizes中的信息合并到output.map中(需要编写脚本处理)。但是,用户可能希望一步完成,所以我们可以编写一个脚本将整个编译和生成合并文件的过程自动化。另外,我们也可以尝试使用ld的`--print-symbol-sizes`选项,并将标准错误重定向一个文件,然后将其与map文件合并。例如:```gcc-ooutput...-Wl,-Map=output.map-Wl,--print-symbol-sizes2>output.sizes```然后,我们可以将output.sizes的内容附加到output.map中。注意:`--print-symbol-sizes`选项输出的格式如下:```<file>(<section>):size<size><symbol>```我们可以编写一个简单的脚本将这种格式的信息整合到map文件的符号表中。但是,需要注意的是,map文件中的符号地址是链接后的地址,而`--print-symbol-sizes`输出的只是每个符号的大小,并没有地址。因此,合并时需要根据符号名称来匹配。然而,由于符号名称可能重复(比如不同文件中的静态函数),所以匹配可能不准确。因此,这种方法并不完美。因此,更可靠的方法是使用`nm`工具,因为它可以直接从目标文件或可执行文件中获取符号的地址和大小。综上所述,我们建议用户使用后处理的方法:先编译生成可执行文件和map文件,然后使用nm工具生成符号大小信息,最后将两者合并。或者,如果用户不需要在同一个文件中,那么直接查看nm的输出也是可以的。如果用户坚持要在map文件中包含大小,那么我们可以提供一个简单的脚本示例:```bash#!/bin/bash#编译并生成map文件gcc-ooutput"$@"-Wl,-Map=output.map#使用nm获取带大小的符号表,按地址排序(与map文件中的顺序一致)nm--print-size--numeric-sortoutput>output.sizes#合并到map文件(这里简单地将sizes文件附加到map文件末尾)echo"Symbolsizes:">>output.mapcatoutput.sizes>>output.map```这样,生成的output.map文件末尾就会包含符号的大小信息。另外,我们也可以使用`objdump-t`来获取更详细的信息,包括符号的大小。注意:nm输出的符号大小是每个符号在目标文件中的大小,而链接后符号在内存中的布局可能会有重叠(比如相同内容合并)?但通常每个符号的大小在链接后不会改变。因此,我们推荐使用nm的方法。最后,我们还需要考虑用户可能是在嵌入式环境中,或者需要的是整个section的大小,而不是每个符号的大小。如果是section的大小,map文件中已经包含了每个section的大小(在MemoryConfiguration部分之后,有各个section的起始地址和大小)。但用户提到的是“size统计信息”,可能是指每个符号的大小。如果用户需要的是section的大小,那么map文件已经包含。如果是指每个函数/变量的大小,则需要使用上述方法。总结回答:由于标准的GCC链接器生成的map文件不包含每个符号的大小,我们可以通过以下方法获取:1.使用`nm`工具从生成的可执行文件中提取符号大小信息。2.将符号大小信息合并到map文件中。具体步骤见上述脚本示例。相关问题:1.GCC的map文件通常包含哪些信息?2.如何分析可执行文件的内存布局?3.如何减少可执行文件的大小?</think>### GCC编译生成的Map文件缺少Size统计信息的解决方法 在GCC编译过程中,生成的Map文件(链接器映射文件)默认不包含符号(函数/变量)的大小(size)信息。这通常是因为链接器(ld)默认配置所致。以下是具体原因和解决方案: #### 原因分析 1. **默认行为限制** GCC的链接器选项`-Map`生成的Map文件主要包含: - 内存区域布局 - 符号地址分配 - 库依赖关系 - Section起始地址 但**不包含符号的大小信息**(如函数/变量占用的字节数)[^1]。 2. **符号表输出差异** Map文件侧重于地址映射和内存分配,而符号大小信息通常需要通过`nm`或`objdump`工具单独提取[^2]。 --- #### 解决方案 ##### 方法1:使用`nm`工具提取符号大小 通过`nm`命令直接获取可执行文件中的符号大小: ```bash nm --print-size --numeric-sort your_executable | grep -i "text\|data" ``` - `--print-size`:显示符号大小 - `--numeric-sort`:按地址排序 - 输出示例: `0000000000401120 0000001d T main` (地址 | 大小 | 类型 | 符号名) ##### 方法2:修改链接器脚本(高级) 在自定义链接器脚本中添加`SIZEOF`命令: ```ld SECTIONS { .text : { /* 输出.text段内符号的大小 */ PROVIDE(__text_start = .); *(.text) PROVIDE(__text_end = .); __text_size = __text_end - __text_start; /* 计算大小 */ } } ``` 编译时指定脚本: ```bash gcc -Wl,-T custom_script.ld -Wl,-Map=output.map ... ``` ##### 方法3:结合`objdump`生成详细报告 ```bash objdump -t --section-headers your_executable > detailed_sizes.txt ``` - `-t`:显示符号表(含大小) - `--section-headers`:列出各段大小 --- #### 验证步骤 1. 编译时生成Map文件: ```bash gcc -Wl,-Map=output.map -o your_executable source.c ``` 2. 使用`nm`检查符号大小: ```bash nm --size-sort your_executable ``` 3. 若输出中无`size`列,表明Map文件确实不包含此信息;若有则检查GCC版本兼容性。 > **注意**:符号大小信息实际存储在ELF文件头中,Map文件仅作为辅助调试工具,如需完整符号元数据建议直接分析可执行文件[^4]。 --- #### 附加调试建议 - 使用`-Wl,--stats`选项获取内存统计: ```bash gcc -Wl,--stats -o output source.c ``` - 启用详细链接日志: ```bash gcc -Wl,--verbose -Wl,-Map=output.map ... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值