Programming/C Win32 MFC

c malloc 이후 free 시에 원인불명으로 죽는 경우

구차니 2026. 1. 16. 10:44

비슷한걸 만들어 보려고 하는데 영 안되는데 신기한 옵션을 찾아서 글 써봄

의도적으로 heap을 넘기는 코드를 작성하고 free() 시에 정말 segmentation fault 가 뜨나 해보는데

$ cat t2.c 
#include <stdio.h>
#include <stdlib.h>

void main()
{
int *arr = NULL;
arr = (int*)malloc(10 * sizeof(int));
int idx = 0;
for(idx = 0; idx < 10000; idx++)
arr[idx] = idx;

printf("before\n");
fflush(stdout);

free(arr);

printf("after\n");
fflush(stdout);
}

 

아쉽게도 free가 아니라 arr[idx] 에서 범위를 넘어서 에러가 발생함

$ gcc t2.c -g
$ ./a.out 
malloc(): corrupted top size
중지됨 (코어 덤프됨)

 

fsanitize 라는 플래그를 주면 좀더 잡아 준다는데 컴파일 타임이 아니라 런타임에 작동한다.

해당 플래그를 추가하면 빌드된 용량이 증가한다.

$ gcc t2.c -g -fsanitize=address
$ ls -al
합계 40
-rwxrwxr-x  1 minimonk minimonk 23536  1월 16 10:33 a.out
-rw-rw-r--  1 minimonk minimonk   271  1월 16 10:30 t2.c

$ gcc t2.c -g
$ ls -al
합계 36
-rwxrwxr-x  1 minimonk minimonk 18704  1월 16 10:35 a.out
-rw-rw-r--  1 minimonk minimonk   271  1월 16 10:30 t2.c

[링크 :https://k0n9.tistory.com/entry/AddressSanitizer]

[링크 : https://stackoverflow.com/questions/58262749/how-to-use-gcc-with-fsanitize-address]

 

실행해서 터트리면 아래와 같이 먼가 나오는데, 엄청 컬러풀하게 터진다.

눈에 들어오는건 summay 항목의 heap-buffer-overflow

특이한게 배열 loop 돌다 터지는게 아니라 다 돌고 나서 free 가려다가 터진다. 신기하네

$ gcc t2.c -g -fsanitize=address
$ ./a.out 
=================================================================
==2713847==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x504000000038 at pc 0x609d568b42e0 bp 0x7ffdaa34e820 sp 0x7ffdaa34e810
WRITE of size 4 at 0x504000000038 thread T0
    #0 0x609d568b42df in main /home/minimonk/work/src/malloc/t2.c:9
    #1 0x7cc2e8429d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #2 0x7cc2e8429e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #3 0x609d568b41a4 in _start (/home/minimonk/work/src/malloc/a.out+0x11a4)

0x504000000038 is located 0 bytes to the right of 40-byte region [0x504000000010,0x504000000038)
allocated by thread T0 here:
    #0 0x7cc2e88b4887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x609d568b4286 in main /home/minimonk/work/src/malloc/t2.c:7
    #2 0x7cc2e8429d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/minimonk/work/src/malloc/t2.c:9 in main
Shadow bytes around the buggy address:
  0x0a087fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0a087fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0a087fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0a087fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0a087fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0a087fff8000: fa fa 00 00 00 00 00[fa]fa fa fa fa fa fa fa fa
  0x0a087fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0a087fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0a087fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0a087fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0a087fff8050: 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
==2713847==ABORTING

 

idx 값을 보면 10000번 돌았는데

printf 하려고 하면 바로 malloc(): corrupted top size 하면서 터진다.

$ gdb ./a.out 
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...
(gdb) l
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 void main()
5 {
6 int *arr = NULL;
7 arr = (int*)malloc(10 * sizeof(int));
8 int idx = 0;
9 for(idx = 0; idx < 10000; idx++)
10 arr[idx] = idx;
(gdb) l 11
6 int *arr = NULL;
7 arr = (int*)malloc(10 * sizeof(int));
8 int idx = 0;
9 for(idx = 0; idx < 10000; idx++)
10 arr[idx] = idx;
11
12 printf("before\n");
13 fflush(stdout);
14
15 free(arr);
(gdb) b 12
Breakpoint 1 at 0x1201: file t2.c, line 12.
(gdb) r
Starting program: /home/minimonk/work/src/malloc/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at t2.c:12
12 printf("before\n");
(gdb) print idx
$1 = 10000
(gdb) n
malloc(): corrupted top size

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737353705280) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: 그런 파일이나 디렉터리가 없습니다.

 

그래서 printf / fflush 주석처리하고 free를 바로 브레이크 포인트 잡아서 해도 동일하게 

루프 종료되면서 바로 에러가 나는 것 같기도...

15 free(arr);
(gdb) c
Continuing.
malloc(): corrupted top size

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737353705280) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: 그런 파일이나 디렉터리가 없습니다.
(gdb)