c
[C] free할 때 주의할 점
ohojee
2022. 12. 28. 15:46
free가 동적할당된 메모리를 free해준다는 개념은 알고 있었는데 자세하게 이해하고 있지는 않았다.
그래서 아래와 같은 코드를 작성했다.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *str = (char *)malloc(sizeof(char) * 40);
char *result;
for (int i = 0; i < 5; i++)
{
str[i] = i + '0';
printf("%c\n", str[i]);
}
result = str;
free(str);
for (int i = 5; i < 10; i++)
{
result[i] = i + '0';
printf("%c\n", result[i]);
}
return ('a');
}
str에 동적할당을 해주고 result에 str을 넘겨줬다.
그 후 str을 free해주고 result에 값을 넣으려고 하니 아래와 같은 메모리 오류가 발생했다.
==1598==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000000355 at pc 0x000104fcddd2 bp 0x7ffeeac35840 sp 0x7ffeeac35838
WRITE of size 1 at 0x604000000355 thread T0
#0 0x104fcddd1 in main test.c:17
#1 0x7fff720bbcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)
0x604000000355 is located 5 bytes inside of 40-byte region [0x604000000350,0x604000000378)
freed by thread T0 here:
#0 0x1050252c6 in wrap_free+0xa6 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x492c6)
#1 0x104fcdd60 in main test.c:14
#2 0x7fff720bbcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)
previously allocated by thread T0 here:
#0 0x10502517d in wrap_malloc+0x9d (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x4917d)
#1 0x104fcdc58 in main test.c:6
#2 0x7fff720bbcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)
SUMMARY: AddressSanitizer: heap-use-after-free test.c:17 in main
Shadow bytes around the buggy address:
0x1c0800000010: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
0x1c0800000020: fa fa 00 00 00 00 00 05 fa fa 00 00 00 00 00 00
0x1c0800000030: fa fa 00 00 00 00 00 05 fa fa 00 00 00 00 00 00
0x1c0800000040: fa fa 00 00 00 00 00 07 fa fa 00 00 00 00 00 00
0x1c0800000050: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
=>0x1c0800000060: fa fa 00 00 00 00 00 05 fa fa[fd]fd fd fd fd fa
0x1c0800000070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0800000080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0800000090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c08000000a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c08000000b0: 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
==1598==ABORTING
zsh: abort ./a.out
free를 해주고 그 주소에 왜 또 다시 접근하냐는 얘기인데
str과 result의 주소값이 똑같은 상태에서 str을 free해주면 result에 속해있는 주소값이 할당해제 되는 것이다.
애초에 free가 그 주소에 할당된 메모리를 해제해주는 것이기에 아주 당연한 소리지만 나에게는 헷갈리는 개념이었다.