-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
47910f0
commit 9f0e95a
Showing
29 changed files
with
1,473 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# 《100个gcc小技巧》 | ||
|
||
一个关于gcc使用小技巧的文档。100,在这里可能只是表明很多;具体的数目取决于您的参与和贡献。 | ||
|
||
## 在线阅读 | ||
[开始阅读](<https://github.com/hellogcc/100-gcc-tips/blob/master/src/index.md>) | ||
|
||
## 如何参与 | ||
|
||
直接发PULL REQUEST,或与我们联系。 | ||
|
||
增加一个小技巧的步骤: | ||
|
||
1. 在src目录下新增一个md文件,参照现有文件的格式风格,编写一个小技巧 | ||
markdown语法参见 http://wowubuntu.com/markdown/ | ||
md文件编写可以使用在线所见即所得编辑器 https://www.zybuluo.com/mdeditor | ||
2. 在index.md中为新md文件增加一个索引,可以放到已有分类中,或增加一个分类 | ||
3. 如果预览下没有问题,OK! | ||
|
||
本地生成html的步骤: | ||
|
||
1. 确保[go](http://code.google.com/p/go)和[md2min](https://github.com/fairlyblank/md2min)已经安装并可用 | ||
2. 直接运行build.sh | ||
3. 如果顺利,会在html目录下生成所有的html文件 | ||
|
||
## 联系方式 | ||
|
||
- [博客网站](http://www.hellogcc.org) | ||
- 在线讨论问题:IRC, freenode, #hellogcc房间 | ||
- [邮件列表](http://www.freelists.org/list/hellogcc) (发信需要先订阅) | ||
|
||
## 版权 | ||
|
||
本文档版权归贡献者所有。 | ||
|
||
## 授权许可 | ||
|
||
本文档使用的是[GNU Free Documentation License](http://www.gnu.org/licenses/fdl.html)。 | ||
|
||
## 致谢 | ||
|
||
- 各位参与者 | ||
|
||
## 其它资源 | ||
|
||
- [GCC在线手册](https://gcc.gnu.org/onlinedocs/gcc) | ||
|
149 changes: 149 additions & 0 deletions
149
00~快速开始/01~编译与运行/编译器/gcc/99~参考资料/100 GCC Tips/address-sanitizer.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
# 利用 Address Sanitizer 工具检查内存访问错误 | ||
|
||
## 例子 | ||
|
||
a.c: | ||
#include <stdio.h> | ||
|
||
int main(void) { | ||
// your code goes here | ||
int a[3] = {0}; | ||
a[3] = 1; | ||
|
||
printf("%d\n", a[3]); | ||
return 0; | ||
} | ||
|
||
b.c: | ||
#include <stdio.h> | ||
#include <malloc.h> | ||
|
||
int main(void) { | ||
int *p = NULL; | ||
|
||
p = malloc(10 * sizeof(int)); | ||
free(p); | ||
*p = 3; | ||
return 0; | ||
} | ||
|
||
## 技巧 | ||
|
||
gcc 从`4.8`版本起,集成了`Address Sanitizer`工具,可以用来检查内存访问的错误(编译时指定“`-fsanitize=address`”)。以上面`a.c`程序为例: | ||
|
||
gcc -fsanitize=address -g -o a a.c | ||
|
||
执行`a`程序: | ||
|
||
[root@localhost nan]# ./a | ||
================================================================= | ||
==539==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff3a152c9c at pc 0x4009b6 bp 0x7fff3a152c60 sp 0x7fff3a152c58 | ||
WRITE of size 4 at 0x7fff3a152c9c thread T0 | ||
#0 0x4009b5 in main /home/nan/a.c:6 | ||
#1 0x34e421ed1c in __libc_start_main (/lib64/libc.so.6+0x34e421ed1c) | ||
#2 0x4007b8 (/home/nan/a+0x4007b8) | ||
|
||
Address 0x7fff3a152c9c is located in stack of thread T0 at offset 44 in frame | ||
#0 0x400907 in main /home/nan/a.c:3 | ||
|
||
This frame has 1 object(s): | ||
[32, 44) 'a' <== Memory access at offset 44 overflows this variable | ||
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext | ||
(longjmp and C++ exceptions *are* supported) | ||
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/nan/a.c:6 main | ||
Shadow bytes around the buggy address: | ||
0x100067422540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x100067422550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x100067422560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x100067422570: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x100067422580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 | ||
=>0x100067422590: f1 f1 00[04]f4 f4 f3 f3 f3 f3 00 00 00 00 00 00 | ||
0x1000674225a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x1000674225b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x1000674225c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x1000674225d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
0x1000674225e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
Shadow byte legend (one shadow byte represents 8 application bytes): | ||
Addressable: 00 | ||
Partially addressable: 01 02 03 04 05 06 07 | ||
Heap left redzone: fa | ||
Heap right redzone: fb | ||
Freed heap region: fd | ||
Stack left redzone: f1 | ||
Stack mid redzone: f2 | ||
Stack right redzone: f3 | ||
Stack partial redzone: f4 | ||
Stack after return: f5 | ||
Stack use after scope: f8 | ||
Global redzone: f9 | ||
Global init order: f6 | ||
Poisoned by user: f7 | ||
Contiguous container OOB:fc | ||
ASan internal: fe | ||
==539==ABORTING | ||
|
||
可以看到,执行程序时检测出了`a`数组的越界访问(`a[3] = 1`)。 | ||
|
||
再看一下`b`程序: | ||
|
||
gcc -fsanitize=address -g -o b b.c | ||
|
||
执行`b`程序: | ||
|
||
[root@localhost nan]# ./b | ||
================================================================= | ||
==1951==ERROR: AddressSanitizer: heap-use-after-free on address 0x60400000dfd0 at pc 0x4007f9 bp 0x7fff34277bb0 sp 0x7fff34277ba8 | ||
WRITE of size 4 at 0x60400000dfd0 thread T0 | ||
#0 0x4007f8 in main /home/nan/b.c:9 | ||
#1 0x34e421ed1c in __libc_start_main (/lib64/libc.so.6+0x34e421ed1c) | ||
#2 0x400658 (/home/nan/b+0x400658) | ||
|
||
0x60400000dfd0 is located 0 bytes inside of 40-byte region [0x60400000dfd0,0x60400000dff8) | ||
freed by thread T0 here: | ||
#0 0x7fbbb7a7d057 in __interceptor_free /opt/gcc-4.9.2/src/gcc-4.9.2/libsanitizer/asan/asan_malloc_linux.cc:62 | ||
#1 0x4007c1 in main /home/nan/b.c:8 | ||
#2 0x34e421ed1c in __libc_start_main (/lib64/libc.so.6+0x34e421ed1c) | ||
|
||
previously allocated by thread T0 here: | ||
#0 0x7fbbb7a7d26f in __interceptor_malloc /opt/gcc-4.9.2/src/gcc-4.9.2/libsanitizer/asan/asan_malloc_linux.cc:72 | ||
#1 0x4007b1 in main /home/nan/b.c:7 | ||
#2 0x34e421ed1c in __libc_start_main (/lib64/libc.so.6+0x34e421ed1c) | ||
|
||
SUMMARY: AddressSanitizer: heap-use-after-free /home/nan/b.c:9 main | ||
Shadow bytes around the buggy address: | ||
0x0c087fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
=>0x0c087fff9bf0: fa fa fa fa fa fa fa fa fa fa[fd]fd fd fd fd fa | ||
0x0c087fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
0x0c087fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
Shadow byte legend (one shadow byte represents 8 application bytes): | ||
Addressable: 00 | ||
Partially addressable: 01 02 03 04 05 06 07 | ||
Heap left redzone: fa | ||
Heap right redzone: fb | ||
Freed heap region: fd | ||
Stack left redzone: f1 | ||
Stack mid redzone: f2 | ||
Stack right redzone: f3 | ||
Stack partial redzone: f4 | ||
Stack after return: f5 | ||
Stack use after scope: f8 | ||
Global redzone: f9 | ||
Global init order: f6 | ||
Poisoned by user: f7 | ||
Contiguous container OOB:fc | ||
ASan internal: fe | ||
==1951==ABORTING | ||
|
||
执行程序时检测出了访问释放内存的错误(`*p = 3`)。 | ||
详情参见[gcc 手册](https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Debugging-Options.html#index-fsanitize_003daddress-593) | ||
|
||
## 贡献者 | ||
|
||
nanxiao |
42 changes: 42 additions & 0 deletions
42
00~快速开始/01~编译与运行/编译器/gcc/99~参考资料/100 GCC Tips/cast-lose-precision.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# error: cast from ... to ... loses precision | ||
|
||
## 例子 | ||
|
||
#include <iostream> | ||
|
||
class Foo { | ||
public: | ||
void print() const { | ||
std::cout << (int)(this) << "\n"; | ||
} | ||
}; | ||
|
||
int main() | ||
{ | ||
class Foo foo; | ||
|
||
foo.print(); | ||
return 0; | ||
} | ||
|
||
## 技巧 | ||
|
||
在 g++编译上面的例子,会报如下错误: | ||
|
||
$ g++ foo.cc | ||
foo.cc: In member function ‘void Foo::print() const’: | ||
foo.cc:6:28: error: cast from ‘const Foo*’ to ‘int’ loses precision [-fpermissive] | ||
|
||
这是一个强制类型转换的错误,你可以修改源代码为: | ||
|
||
std::cout << (int*)(this) << "\n"; | ||
|
||
即可。 | ||
|
||
如果,你不想(或不能)去修改源程序,只是应为升级了 gcc 而带来了这样的错误,那么也可以使用`-fpermissive`选项,将错误降低为警告: | ||
|
||
$ g++ foo.cc -fpermissive | ||
foo.cc: In member function ‘void Foo::print() const’: | ||
foo.cc:6:28: warning: cast from ‘const Foo*’ to ‘int’ loses precision [-fpermissive] | ||
|
||
详情参见[gcc 手册](https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#index-fpermissive-166) |
33 changes: 33 additions & 0 deletions
33
00~快速开始/01~编译与运行/编译器/gcc/99~参考资料/100 GCC Tips/define-macro.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# 在命令行中预定义宏 | ||
|
||
## 例子 | ||
|
||
#include <stdio.h> | ||
|
||
int main (void) | ||
{ | ||
int i, sum; | ||
|
||
for (i = 1, sum = 0; i <= 10; i++) | ||
{ | ||
sum += i; | ||
#ifdef DEBUG | ||
printf ("sum += %d is %d\n", i, sum); | ||
#endif | ||
} | ||
printf ("total sum is %d\n", sum); | ||
|
||
return 0; | ||
} | ||
|
||
## 技巧 | ||
|
||
使用`-D`选项可以在命令行中预定义一个宏,比如: | ||
|
||
$ gcc -D DEBUG macro.c | ||
|
||
中间可以没有空格: | ||
|
||
$ gcc -DDEBUG macro.c | ||
|
||
详情参见[gcc 手册](https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html#Preprocessor-Options) |
9 changes: 9 additions & 0 deletions
9
00~快速开始/01~编译与运行/编译器/gcc/99~参考资料/100 GCC Tips/diagnostics-color.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# 打印彩色诊断信息 | ||
|
||
## 技巧 | ||
|
||
这是 gcc-4.9 新增的功能,可以通过定义环境变量`GCC_COLORS`来彩色打印诊断信息。 | ||
|
||
也可以使用选项`-fdiagnostics-color`来设定。 | ||
|
||
详情参见[gcc 手册](https://gcc.gnu.org/onlinedocs/gcc/Language-Independent-Options.html#Language-Independent-Options) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# 信息显示 | ||
* [打印gcc预定义的宏信息](print-predefined-macros.md) | ||
* [打印gcc执行的子命令](print-commands-only.md) | ||
* [打印优化级别的对应选项](print-level-options.md) | ||
* [打印彩色诊断信息](diagnostics-color.md) | ||
* [打印头文件搜索路径](print-header-search-dir.md) | ||
* [打印连接库的具体路径](print-file-name.md) | ||
|
||
# 预处理 | ||
* [生成没有行号标记的预处理文件](inhibit-linemarkers.md) | ||
* [在命令行中预定义宏](define-macro.md) | ||
* [在命令行中取消宏定义](undefine-macro.md) | ||
|
||
# 汇编 | ||
* [把选项传给汇编器](pass-options-to-assembler.md) | ||
* [生成有详细信息的汇编文件](verbose-asm.md) | ||
|
||
# 调试 | ||
* [利用Address Sanitizer工具检查内存访问错误](address-sanitizer.md) | ||
* [利用Thread Sanitizer工具检查数据竞争的问题](thread-sanitizer.md) | ||
|
||
# 连接 | ||
* [把选项传给连接器](pass-options-to-linker.md) | ||
* [设置动态连接器](set-dynamic-linker.md) | ||
|
||
# 函数属性 | ||
* [禁止函数被优化掉](must-emit-function-code.md) | ||
* [强制函数inline](must-forceinline-function-code.md) | ||
|
||
# 常见错误 | ||
* [error: cast from ... to ... loses precision](cast-lose-precision.md) | ||
* [all warnings being treated as errors](warnings-treated-as-errors.md) | ||
* [gdb无法调试gcc编译的程序](specify-dwarf-version.md) | ||
|
||
# 其它 | ||
* [只做语法检查](syntax-only.md) | ||
* [保存临时文件](save-temps.md) | ||
* [打开警告信息](turn-on-warnings.md) | ||
* [指定语言类型](specify-language.md) | ||
* [改变结构体成员的字节对齐](pack-struct.md) | ||
|
37 changes: 37 additions & 0 deletions
37
00~快速开始/01~编译与运行/编译器/gcc/99~参考资料/100 GCC Tips/inhibit-linemarkers.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# 生成没有行号标记的预处理文件 | ||
|
||
## 技巧 | ||
|
||
有时编译程序会遇到如下类似的错误, | ||
|
||
In file included from foo.c:15, | ||
from a.h:45, | ||
b.h:53: error: ... ... | ||
|
||
如果错误是由于你所定义的一个很复杂的宏所引起的,你可能会需要先手动编译生成相应的预处理文件,查看下预处理文件中的宏扩展代码。比如,先运行 | ||
|
||
gcc -E foo.c -o foo.i | ||
|
||
来生成 foo.i 预处理文件。然后,还可以尝试手动修改、编译这个预处理文件。 | ||
|
||
但是,由于生成的预处理文件中含有行号标记(linemarker),所以,运行 | ||
|
||
gcc -c foo.i -o foo.o | ||
|
||
所得到的错误行号信息还是跟最初的一样,如果可以将预处理文件中的行号标记都去掉,似乎会有些帮助。 | ||
|
||
幸好,gcc 提供了这个选项: | ||
|
||
> -P | ||
> Inhibit generation of linemarkers in the output from the | ||
> preprocessor. This might be useful when running the preprocessor on | ||
> something that is not C code, and will be sent to a program which | ||
> might be confused by the linemarkers. | ||
运行 | ||
|
||
gcc -E -P foo.c -o foo.i | ||
|
||
即可。 | ||
|
||
详情参见[gcc 手册](https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html#Preprocessor-Options) |
23 changes: 23 additions & 0 deletions
23
00~快速开始/01~编译与运行/编译器/gcc/99~参考资料/100 GCC Tips/must-emit-function-code.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# 禁止函数被优化掉 | ||
|
||
## 例子 | ||
|
||
#if (GCC_VERSION > 4000) | ||
#define DEBUG_FUNCTION __attribute__ ((__used__)) | ||
#define DEBUG_VARIABLE __attribute__ ((__used__)) | ||
#else | ||
#define DEBUG_FUNCTION | ||
#define DEBUG_VARIABLE | ||
#endif | ||
|
||
DEBUG_FUNCTION void | ||
debug_bb (basic_block bb) | ||
{ | ||
dump_bb (bb, stderr, 0); | ||
} | ||
|
||
## 技巧 | ||
|
||
上面的例子是 gcc 的源码。使用 gcc 的扩展功能——函数属性`__attribute__ ((__used__))`,可以指定该函数是有用的,不能被优化掉。 | ||
|
||
详情参见[gcc 手册](https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#Function-Attributes) |
Oops, something went wrong.