|
发表于 2022-3-6 14:29:39
|
显示全部楼层
其实gcc就自带了内存检查的功能(运行时检查),只是默认没有开启
当然,要你的gcc是新版本的,旧版本的gcc有可能用不了
我不知道gcc从哪一个版本开始添加的内存检查功能,也不关心
反正我的gcc是新版本的,可以用内存检查,^_^
- $ gcc --version
- gcc (GCC) 11.2.0
- Copyright (C) 2021 Free Software Foundation, Inc.
- This is free software; see the source for copying conditions. There is NO
- warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- $
复制代码
谈不上最新,但是够用
我没有在windows中尝试过gcc的内存检查功能,可能也能用?不知道
- $ cat main.c
- #include <stdio.h>
- #include <stdlib.h>
- int main(void) {
- int *p = malloc(sizeof(*p));
- *p = 123;
- printf("%d\n", *p);
- //free(p);
- return 0;
- }
- $ gcc -g -Wall -fsanitize=undefined -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer -o main main.c
- $ ./main
- 123
- =================================================================
- ==987243==ERROR: LeakSanitizer: detected memory leaks
- Direct leak of 4 byte(s) in 1 object(s) allocated from:
- #0 0x7ff146f8cdd9 in __interceptor_malloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
- #1 0x560d4f9611ba in main /tmp/C/main.c:5
- #2 0x7ff14638330f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)
- SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
- $ vim main.c
- $ cat main.c
- #include <stdio.h>
- #include <stdlib.h>
- int main(void) {
- int *p = malloc(sizeof(*p));
- *p = 123;
- printf("%d\n", *p);
- free(p);
- return 0;
- }
- $ gcc -g -Wall -fsanitize=undefined -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer -o main main.c
- $ ./main
- 123
- $
复制代码
- $ cat main.c
- #include <stdio.h>
- #include <stdlib.h>
- int main(void) {
- int array[10] = {0};
- int n;
- scanf("%d", &n);
- printf("%d\n", array[n]);
- return 0;
- }
- $ gcc -g -Wall -fsanitize=undefined -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer -o main main.c
- $ ./main
- 10
- main.c:8:25: runtime error: index 10 out of bounds for type 'int [10]'
- main.c:8:5: runtime error: load of address 0x7ffdd3b78528 with insufficient space for an object of type 'int'
- 0x7ffdd3b78528: note: pointer points here
- 00 00 00 00 00 a6 3c 78 98 8a 28 12 c0 84 b7 d3 fd 7f 00 00 c0 7a fa 5c bf 7f 00 00 41 00 00 00
- ^
- =================================================================
- ==988335==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdd3b78528 at pc 0x55c36c0db465 bp 0x7ffdd3b784c0 sp 0x7ffdd3b784b0
- READ of size 4 at 0x7ffdd3b78528 thread T0
- #0 0x55c36c0db464 in main /tmp/C/main.c:8
- #1 0x7fbf5ba2030f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)
- #2 0x7fbf5ba203c0 in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0)
- #3 0x55c36c0db124 in _start (/tmp/C/main+0x1124)
- Address 0x7ffdd3b78528 is located in stack of thread T0 at offset 88 in frame
- #0 0x55c36c0db208 in main /tmp/C/main.c:4
- This frame has 2 object(s):
- [32, 36) 'n' (line 6)
- [48, 88) 'array' (line 5) <== Memory access at offset 88 overflows this variable
- HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
- (longjmp and C++ exceptions *are* supported)
- SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/C/main.c:8 in main
- Shadow bytes around the buggy address:
- 0x10003a767050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a767060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a767070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a767080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a767090: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f2
- =>0x10003a7670a0: 00 00 00 00 00[f3]f3 f3 f3 f3 00 00 00 00 00 00
- 0x10003a7670b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a7670c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a7670d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a7670e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x10003a7670f0: 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
- 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
- ==988335==ABORTING
- $
- $
- $
- $
- $
- $
- $ vim main.c
- $ cat main.c
- #include <stdio.h>
- #include <stdlib.h>
- int main(void) {
- int array[10] = {0};
- int n;
- scanf("%d", &n);
- array[n] = 123;
- //printf("%d\n", array[n]);
- return 0;
- }
- $ gcc -g -Wall -fsanitize=undefined -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer -o main main.c
- main.c: In function ‘main’:
- main.c:5:9: warning: variable ‘array’ set but not used [-Wunused-but-set-variable]
- 5 | int array[10] = {0};
- | ^~~~~
- $ ./main
- 10
- main.c:8:10: runtime error: index 10 out of bounds for type 'int [10]'
- main.c:8:14: runtime error: store to address 0x7ffec538b1b8 with insufficient space for an object of type 'int'
- 0x7ffec538b1b8: note: pointer points here
- 00 00 00 00 00 66 e4 ec 51 d5 04 37 50 b1 38 c5 fe 7f 00 00 c0 4a 7a 7c eb 7f 00 00 41 00 00 00
- ^
- =================================================================
- ==988793==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffec538b1b8 at pc 0x55d75b226465 bp 0x7ffec538b150 sp 0x7ffec538b140
- WRITE of size 4 at 0x7ffec538b1b8 thread T0
- #0 0x55d75b226464 in main /tmp/C/main.c:8
- #1 0x7feb7b21d30f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)
- #2 0x7feb7b21d3c0 in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0)
- #3 0x55d75b226124 in _start (/tmp/C/main+0x1124)
- Address 0x7ffec538b1b8 is located in stack of thread T0 at offset 88 in frame
- #0 0x55d75b226208 in main /tmp/C/main.c:4
- This frame has 2 object(s):
- [32, 36) 'n' (line 6)
- [48, 88) 'array' (line 5) <== Memory access at offset 88 overflows this variable
- HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
- (longjmp and C++ exceptions *are* supported)
- SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/C/main.c:8 in main
- Shadow bytes around the buggy address:
- 0x100058a695e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a695f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a69600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a69610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a69620: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
- =>0x100058a69630: 04 f2 00 00 00 00 00[f3]f3 f3 f3 f3 00 00 00 00
- 0x100058a69640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a69650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a69660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a69670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0x100058a69680: 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
- 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
- ==988793==ABORTING
- $
复制代码
你可能会发现,我有时候用的编译命令是这样的
这个 gcc-debug 其实是一个 alias
- alias gcc-debug='gcc -g -Wall -fsanitize=undefined -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer'
复制代码
其实下面这两个是一样的
- $ gcc -g -Wall -fsanitize=undefined -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer -o main main.c
复制代码
我为了避免每一次编译代码都输入那么一长串,就弄了一个alias
这个报错的内容可以说是很详细了,代码的哪一行,变量的值,堆栈的当前状态
这些都给你列出来了,对debug非常有帮助
大部分的逻辑问题(逻辑错误),gcc的运行时检查都能检查出来
大部分的语法问题(语法错误),gcc的-Wall选项也全都给你指出来了
所以,写的代码很难出问题吧?
还有,其实我这边的报错是彩色的,看起来更舒服,^_^
|
|