如果你想修改可以给你权限编辑,因为我不再更新课本内容。
本章可视化排序工具:里面有排序算法和各种数据结构可视化等,是一个非常不错的学习平台。
附录 gcc 编译内存检测
从本章开始,数组越界,指针非法访问等问题可以使用内存检测工具:参考 Address Sanitizer 用法。这对于数组和野指针非常管用!
#include <stdio.h>
#include <stdlib.h>
int main() {
int *a = (int *)malloc(sizeof(int) * 10);
free(a);
printf("a[0]=%d\n", a[0]);
return 0;
}
编译运行:
:::danger
b12@PC:~/chapter0 $ gcc -fsanitize=address -fno-omit-frame-pointer -out-of-bounds -use-after-free -O1 -Wall -g ./src/intRange.c -o ./bin/intRange
b12@PC:~/chapter0 $ ./bin/intRange
=================================================================
==456==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000000010 at pc 0x7f0191d3128d bp 0x7fffe5744d70 sp 0x7fffe5744d60
READ of size 4 at 0x604000000010 thread T0
#0 0x7f0191d3128c in main src/intRange.c:7
#1 0x7f01910d70b2 in libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#2 0x7f0191d3116d in _start (/home/b12/chapter13/bin/intRange+0x116d)
0x604000000010 is located 0 bytes inside of 40-byte region [0x604000000010,0x604000000038)
freed by thread T0 here:
#0 0x7f01913bd7cf in interceptor_free (/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf)
#1 0x7f0191d3124a in main src/intRange.c:6
#2 0x7f01910d70b2 in libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
previously allocated by thread T0 here:
#0 0x7f01913bdbc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x7f0191d3123f in main src/intRange.c:5
#2 0x7f01910d70b2 in libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-use-after-free src/intRange.c:7 in main
Shadow bytes around the buggy address:
0x0c087fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c087fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c087fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c087fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c087fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c087fff8000: fa fa[fd]fd fd fd fd fa fa fa fa fa fa fa fa fa
0x0c087fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff8050: 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
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==456==ABORTING
:::
我们真的需要每次输入一大串的参数吗?是不是非常麻烦啊!别怕 Linux 中的 alias
别名命令可以替换。
# 1.添加 gcc 别名命令
b12@PC:~$ alias gcc='gcc -fsanitize=address -fno-omit-frame-pointer -out-of-bounds -use-after-free -O1 -Wall -g'
# 2.添加成功
b12@PC:~$ alias
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias gcc='gcc -fsanitize=address -fno-omit-frame-pointer -out-of-bounds -use-after-free -O1 -Wall -g'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
# 3. 删除别名,它就默认回到原来的命令了
b12@PC:~$ unalias gcc
b12@PC:~$ alias
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
因此我们只需要像上面一样,随时改个别名就可以做到一劳永逸,参数随便增加。