Ver3.0 ๐ C์ธ์ด ๋๋ฒ๊น ์์ ์ ๋ณต: GDB์ Valgrind๋ก ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ ์ก์๋ด๊ธฐ

๐ C์ธ์ด ๋๋ฒ๊น ์์ ์ ๋ณต: GDB์ Valgrind๋ก ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ ์ก์๋ด๊ธฐ
์๋ ! ๐ C์ธ์ด๋ก ํ๋ก๊ทธ๋จ ์ง๋ค๊ฐ ๊ฐ์๊ธฐ "Segmentation fault"๋ผ๋ ๋ฌด์๋ฌด์ํ ๋ฉ์์ง๋ฅผ ๋ณธ ์ ์์ง? ์๋๋ฉด ํ๋ก๊ทธ๋จ์ด ๋ฉ์ฉกํ ๋์๊ฐ๋ ๊ฒ ๊ฐ์๋ฐ ์ด๋๊ฐ์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๊ณ ์๋ค๋ ๋๋? ๊ทธ๋ด ๋ ์ฐ๋ฆฌ์๊ฒ ํ์ํ ๊ฑด ๋ฐ๋ก ๊ฐ๋ ฅํ ๋๋ฒ๊น ๋๊ตฌ์ผ! ์ค๋์ C์ธ์ด ๊ฐ๋ฐ์๋ผ๋ฉด ๋ฐ๋์ ์์์ผ ํ GDB์ Valgrind์ ๋ํด ์น๊ตฌ์ฒ๋ผ ํธํ๊ฒ ์ด์ผ๊ธฐํด๋ณผ๊ฒ. ๐
์ฌ์ค ๋๋ฒ๊น ์ ํ๋ก๊ทธ๋๋ฐ์ ์ ๋ฐ ์ด์์ ์ฐจ์งํ๋ค๊ณ ํด๋ ๊ณผ์ธ์ด ์๋์ผ. ์ฝ๋๋ฅผ ์์ฑํ๋ ์๊ฐ๋ณด๋ค ๋ฒ๊ทธ๋ฅผ ์ฐพ๊ณ ๊ณ ์น๋ ์๊ฐ์ด ๋ ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ฑฐ๋ . ํนํ C์ธ์ด๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ๊ด๋ฆฌํด์ผ ํ๊ธฐ ๋๋ฌธ์ ํฌ์ธํฐ ์ค๋ฅ, ๋ฉ๋ชจ๋ฆฌ ๋์, ๋ฒํผ ์ค๋ฒํ๋ก์ฐ ๊ฐ์ ๋ฌธ์ ๋ค์ด ์ ๋ง ์์ฃผ ๋ฐ์ํด. ์ด๋ฐ ๋ฌธ์ ๋ค์ ํจ๊ณผ์ ์ผ๋ก ์ฐพ์๋ด๊ณ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์! ๐
๐ฏ ๋๋ฒ๊น ์ด ์ ์ด๋ ๊ฒ ์ค์ํ ๊น?
ํ๋ก๊ทธ๋๋ฐ์ ์ฒ์ ๋ฐฐ์ธ ๋๋ "์ฝ๋๋ง ์ ์ง๋ฉด ๋๋ ๊ฑฐ ์๋์ผ?"๋ผ๊ณ ์๊ฐํ๊ธฐ ์ฌ์. ํ์ง๋ง ์ค์ ๊ฐ๋ฐ ํ์ฅ์์๋ ์๋ฒฝํ ์ฝ๋๋ฅผ ํ ๋ฒ์ ์์ฑํ๋ ๊ฑด ๊ฑฐ์ ๋ถ๊ฐ๋ฅํด. ํนํ C์ธ์ด๋ ๋ค๋ฅธ ๊ณ ์์ค ์ธ์ด๋ค๊ณผ ๋ฌ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ค์ํ ์ฌ์ง๊ฐ ํจ์ฌ ๋ง์ง. ๐ค
์ํํธ์จ์ด ๊ฐ๋ฐ ํ๋ก์ ํธ์์ ๊ฐ๋ฐ์๋ค์ ํ๊ท ์ ์ผ๋ก ์ ์ฒด ๊ฐ๋ฐ ์๊ฐ์ 50~75%๋ฅผ ๋๋ฒ๊น ์ ์ฌ์ฉํ๋ค๊ณ ํด. ๋ํ ์ํํธ์จ์ด ๋ฒ๊ทธ๋ก ์ธํ ๊ฒฝ์ ์ ์์ค์ ์ฐ๊ฐ ์์กฐ ์์ ๋ฌํ๋ค๋ ์ฐ๊ตฌ ๊ฒฐ๊ณผ๋ ์์ด. ๊ทธ๋งํผ ๋๋ฒ๊น ๋ฅ๋ ฅ์ ํ๋ก๊ทธ๋๋จธ์ ํต์ฌ ์ญ๋์ด๋ผ๊ณ ํ ์ ์์ง!
C์ธ์ด์์ ์์ฃผ ๋ฐ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ์ค๋ฅ๋ค์ ์ดํด๋ณด๋ฉด:
**๋ฉ๋ชจ๋ฆฌ ๋์(Memory Leak)** ๐ง
malloc์ด๋ calloc์ผ๋ก ํ ๋นํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ freeํ์ง ์์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ณ์ ์์ด๋ ๋ฌธ์ ์ผ. ํ๋ก๊ทธ๋จ์ด ์ค๋ ์คํ๋๋ฉด ์์คํ
๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ค ์ก์๋จน์ด์ ๊ฒฐ๊ตญ ํฌ๋์๊ฐ ๋ฐ์ํ ์ ์์ด.
**๋ฒํผ ์ค๋ฒํ๋ก์ฐ(Buffer Overflow)** ๐ฆ
๋ฐฐ์ด์ ํฌ๊ธฐ๋ฅผ ๋์ด์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ๊ฒฝ์ฐ์ผ. ์ด๊ฑด ๋จ์ํ ํ๋ก๊ทธ๋จ์ด ์ฃฝ๋ ๊ฒ์ ๋์ด์ ๋ณด์ ์ทจ์ฝ์ ์ผ๋ก ์ด์ด์ง ์ ์์ด์ ์ ๋ง ์ํํด.
**๋๊ธ๋ง ํฌ์ธํฐ(Dangling Pointer)** ๐ป
์ด๋ฏธ ํด์ ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ผ. ์์ธกํ ์ ์๋ ๋์์ ์ผ์ผํค๊ณ ๋๋ฒ๊น
ํ๊ธฐ๋ ์ ๋ง ๊น๋ค๋ก์.
**์ด์ค ํด์ (Double Free)** โ ๏ธ
๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ ๋ฒ freeํ๋ ๊ฒฝ์ฐ์ธ๋ฐ, ์ด๊ฒ๋ ํ๋ก๊ทธ๋จ ํฌ๋์์ ์ฃผ์ ์์ธ ์ค ํ๋์ผ.
๐ง GDB: ํ๋ก๊ทธ๋๋จธ์ ํ๋ฏธ๊ฒฝ
GDB(GNU Debugger)๋ C์ธ์ด ๊ฐ๋ฐ์๋ค์ด ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋๋ฒ๊ฑฐ์ผ. ๋ฆฌ๋ ์ค ํ๊ฒฝ์์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๊ณ , ํ๋ก๊ทธ๋จ์ ์คํ์ ํ ์ค์ฉ ์ถ์ ํ๋ฉด์ ๋ณ์ ๊ฐ์ ํ์ธํ๊ณ ๋ฌธ์ ๋ฅผ ์ฐพ์๋ผ ์ ์์ด. ๋ง์น ํ๋ฏธ๊ฒฝ์ผ๋ก ์ธํฌ๋ฅผ ๊ด์ฐฐํ๋ฏ์ด ์ฝ๋๋ฅผ ์ธ๋ฐํ๊ฒ ๋ค์ฌ๋ค๋ณผ ์ ์์ง! ๐ฌ
GDB ์ค์น์ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
๋๋ถ๋ถ์ ๋ฆฌ๋ ์ค ๋ฐฐํฌํ์๋ GDB๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ค์น๋์ด ์์ด. ๋ง์ฝ ์๋ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ก ์ค์นํ ์ ์์ด:
# Ubuntu/Debian
sudo apt-get install gdb
# CentOS/RHEL
sudo yum install gdb
# macOS (Homebrew ์ฌ์ฉ)
brew install gdb
GDB๋ก ๋๋ฒ๊น ํ๋ ค๋ฉด ๋จผ์ ํ๋ก๊ทธ๋จ์ ์ปดํ์ผํ ๋ -g ์ต์ ์ ๋ถ์ฌ์ผ ํด. ์ด ์ต์ ์ ๋๋ฒ๊น ์ ๋ณด๋ฅผ ์คํ ํ์ผ์ ํฌํจ์์ผ์ค:
gcc -g -o myprogram myprogram.c
์ด์ GDB๋ฅผ ์คํํด๋ณด์:
gdb ./myprogram
GDB ํต์ฌ ๋ช ๋ น์ด ๋ง์คํฐํ๊ธฐ
GDB๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๋ ค๋ฉด ๋ช ๊ฐ์ง ํต์ฌ ๋ช ๋ น์ด๋ฅผ ์์์ผ ํด. ์ฒ์์๋ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ๋ช ๋ฒ ์จ๋ณด๋ฉด ๊ธ๋ฐฉ ์ต์ํด์ง ๊ฑฐ์ผ! ๐
| ๋ช ๋ น์ด | ์ฝ์ด | ์ค๋ช |
|---|---|---|
| run | r | ํ๋ก๊ทธ๋จ ์คํ |
| break | b | ์ค๋จ์ (breakpoint) ์ค์ |
| next | n | ๋ค์ ์ค๋ก ์ด๋ (ํจ์ ๋ด๋ถ๋ก ๋ค์ด๊ฐ์ง ์์) |
| step | s | ๋ค์ ์ค๋ก ์ด๋ (ํจ์ ๋ด๋ถ๋ก ๋ค์ด๊ฐ) |
| continue | c | ๋ค์ ์ค๋จ์ ๊น์ง ์คํ |
| p | ๋ณ์ ๊ฐ ์ถ๋ ฅ | |
| backtrace | bt | ํธ์ถ ์คํ ์ถ๋ ฅ |
| quit | q | GDB ์ข ๋ฃ |
์ค์ ์์ : ์ธ๊ทธ๋ฉํ ์ด์ ํดํธ ์ก๊ธฐ
์, ์ด์ ์ค์ ๋ก ๋ฒ๊ทธ๊ฐ ์๋ ์ฝ๋๋ฅผ GDB๋ก ๋๋ฒ๊น ํด๋ณด์. ๋ค์์ ์ ํ์ ์ธ ์ธ๊ทธ๋ฉํ ์ด์ ํดํธ๋ฅผ ์ผ์ผํค๋ ์ฝ๋์ผ:
#include <stdio.h>
#include <string.h>
void buggy_function(char *str) {
char buffer[10];
strcpy(buffer, str); // ์ํํ ์ฝ๋!
printf("Buffer: %s\n", buffer);
}
int main() {
char *long_string = "This is a very long string that will overflow";
buggy_function(long_string);
return 0;
}
์ด ์ฝ๋๋ฅผ ์ปดํ์ผํ๊ณ ์คํํ๋ฉด ์ธ๊ทธ๋ฉํ ์ด์ ํดํธ๊ฐ ๋ฐ์ํ ๊ฑฐ์ผ. GDB๋ก ๋๋ฒ๊น ํด๋ณด์:
$ gcc -g -o buggy buggy.c
$ gdb ./buggy
(gdb) run
Starting program: /path/to/buggy
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e5c123 in strcpy () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) backtrace
#0 0x00007ffff7e5c123 in strcpy () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x0000555555555189 in buggy_function (str=0x555555556004) at buggy.c:6
#2 0x00005555555551b7 in main () at buggy.c:12
(gdb) frame 1
#1 0x0000555555555189 in buggy_function (str=0x555555556004) at buggy.c:6
6 strcpy(buffer, str);
(gdb) print str
$1 = 0x555555556004 "This is a very long string that will overflow"
(gdb) print sizeof(buffer)
$2 = 10
๋ณด๋ค์ํผ GDB๋ ์ ํํ ์ด๋์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋์ง ์๋ ค์ค. backtrace ๋ช ๋ น์ผ๋ก ํจ์ ํธ์ถ ์คํ์ ํ์ธํ๊ณ , print ๋ช ๋ น์ผ๋ก ๋ณ์ ๊ฐ์ ํ์ธํ ์ ์์ด. ์ด ๊ฒฝ์ฐ 46๋ฐ์ดํธ ๋ฌธ์์ด์ 10๋ฐ์ดํธ ๋ฒํผ์ ๋ณต์ฌํ๋ ค๊ณ ํด์ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ ๊ฑฐ์ผ!
break buggy_function์ด๋ผ๊ณ ํ๋ฉด ํด๋น ํจ์์ ์์ ๋ถ๋ถ์ ์ค๋จ์ ์ด ์ค์ ๋ผ. ๋ํ ์กฐ๊ฑด๋ถ ์ค๋จ์ ๋ ์ค์ ํ ์ ์์ด: break 10 if x > 5์ฒ๋ผ ๋ง์ด์ผ!
GDB์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค
GDB๋ ๊ธฐ๋ณธ ๊ธฐ๋ฅ ์ธ์๋ ์ ๋ง ๊ฐ๋ ฅํ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํด. ์ด๋ฐ ๊ธฐ๋ฅ๋ค์ ์๋ฉด ๋๋ฒ๊น ํจ์จ์ด ๋ช ๋ฐฐ๋ ์ฌ๋ผ๊ฐ!
**์์นํฌ์ธํธ(Watchpoint)** ๐
ํน์ ๋ณ์์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํ๋ก๊ทธ๋จ์ ๋ฉ์ถ๊ฒ ํ ์ ์์ด. ์ธ์ ์ด๋์ ๋ณ์๊ฐ ๋ฐ๋๋์ง ์ถ์ ํ๊ธฐ ์ ๋ง ์ข์ง:
(gdb) watch my_variable
Hardware watchpoint 2: my_variable
(gdb) continue
Continuing.
Hardware watchpoint 2: my_variable
Old value = 0
New value = 42
**๋ฉ๋ชจ๋ฆฌ ๋คํ** ๐พ
๋ฉ๋ชจ๋ฆฌ์ ํน์ ์์ญ์ ์ง์ ๋ค์ฌ๋ค๋ณผ ์ ์์ด. ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ๋ง ์ฌ๋ฐ๋ฅธ์ง ํ์ธํ ๋ ์ ์ฉํด:
(gdb) x/10x buffer
0x7fffffffe3b0: 0x73696854 0x20736920 0x65762061 0x6c207972
0x7fffffffe3c0: 0x20676e6f 0x69727473 0x7420676e 0x20746168
**์ญ๋ฐฉํฅ ๋๋ฒ๊น
(Reverse Debugging)** โฎ๏ธ
์ต์ ๋ฒ์ ์ GDB๋ ํ๋ก๊ทธ๋จ ์คํ์ ๊ฑฐ๊พธ๋ก ๋๋ฆด ์ ์์ด! ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ง์ ์์ ์ญ์ผ๋ก ์ถ์ ํ๋ฉด์ ์์ธ์ ์ฐพ์ ์ ์์ง:
(gdb) record
(gdb) continue
... (๋ฒ๊ทธ ๋ฐ์)
(gdb) reverse-step
(gdb) reverse-continue
๐ก๏ธ Valgrind: ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ์ ํ์
GDB๊ฐ ํ๋ก๊ทธ๋จ์ ์คํ ํ๋ฆ์ ์ถ์ ํ๋ ๋๊ตฌ๋ผ๋ฉด, Valgrind๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ๊ฐ์ํ๋ ์ ๋ฌธ๊ฐ์ผ. ํนํ Memcheck๋ผ๋ ๋๊ตฌ๋ ๋ฉ๋ชจ๋ฆฌ ๋์, ์๋ชป๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ, ์ด๊ธฐํ๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ๋ฑ์ ์ฐพ์๋ด๋ ๋ฐ ํ์ํด. ๐ต๏ธ
Valgrind ์ค์นํ๊ธฐ
Valgrind๋ ๋๋ถ๋ถ์ ๋ฆฌ๋ ์ค ๋ฐฐํฌํ์์ ์ฝ๊ฒ ์ค์นํ ์ ์์ด:
# Ubuntu/Debian
sudo apt-get install valgrind
# CentOS/RHEL
sudo yum install valgrind
# macOS๋ ๊ณต์ ์ง์์ด ์ ํ์ ์ด์ง๋ง ์๋ํด๋ณผ ์ ์์ด
brew install valgrind
Valgrind ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
Valgrind๋ฅผ ์ฌ์ฉํ๋ ๊ฑด ์ ๋ง ๊ฐ๋จํด. ํ๋ก๊ทธ๋จ ์คํ ๋ช
๋ น ์์ valgrind๋ง ๋ถ์ด๋ฉด ๋ผ:
valgrind ./myprogram
๋ ์์ธํ ์ ๋ณด๋ฅผ ๋ณด๋ ค๋ฉด ์ต์ ์ ์ถ๊ฐํ ์ ์์ด:
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./myprogram
๊ฐ ์ต์ ์ ์๋ฏธ๋ฅผ ์ดํด๋ณด๋ฉด:
- --leak-check=full: ๋ฉ๋ชจ๋ฆฌ ๋์์ ๋ํ ์์ธํ ์ ๋ณด ์ ๊ณต
- --show-leak-kinds=all: ๋ชจ๋ ์ข
๋ฅ์ ๋ฉ๋ชจ๋ฆฌ ๋์ ํ์
- --track-origins=yes: ์ด๊ธฐํ๋์ง ์์ ๊ฐ์ ์ถ์ฒ ์ถ์
์ค์ ์์ : ๋ฉ๋ชจ๋ฆฌ ๋์ ์ฐพ๊ธฐ
๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ์๋ ๊ฐ๋จํ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์:
#include <stdlib.h>
#include <string.h>
char* create_string(const char* text) {
char* str = (char*)malloc(strlen(text) + 1);
strcpy(str, text);
return str;
}
int main() {
for (int i = 0; i < 10; i++) {
char* message = create_string("Hello, World!");
// free(message)๋ฅผ ๊น๋นกํ์ด!
}
return 0;
}
์ด ์ฝ๋๋ฅผ ์ปดํ์ผํ๊ณ Valgrind๋ก ์คํํด๋ณด์:
$ gcc -g -o leak leak.c
$ valgrind --leak-check=full ./leak
==12345== Memcheck, a memory error detector
==12345== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12345== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==12345== Command: ./leak
==12345==
==12345==
==12345== HEAP SUMMARY:
==12345== in use at exit: 140 bytes in 10 blocks
==12345== total heap usage: 11 allocs, 1 frees, 1,164 bytes allocated
==12345==
==12345== 140 (14 direct, 126 indirect) bytes in 10 blocks are definitely lost
==12345== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12345== by 0x108667: create_string (leak.c:5)
==12345== by 0x1086B4: main (leak.c:12)
==12345==
==12345== LEAK SUMMARY:
==12345== definitely lost: 140 bytes in 10 blocks
==12345== indirectly lost: 0 bytes in 0 blocks
==12345== possibly lost: 0 bytes in 0 blocks
==12345== still reachable: 0 bytes in 0 blocks
==12345== suppressed: 0 bytes in 0 blocks
==12345==
==12345== For lists of detected and suppressed errors, rerun with: -s
==12345== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
์! Valgrind๊ฐ ์ ํํ ์ด๋์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋์๋๊ณ ์๋์ง ์๋ ค์ฃผ๋ค! ๐ก 140๋ฐ์ดํธ๊ฐ 10๊ฐ ๋ธ๋ก์์ ๋์๋๊ณ ์๊ณ , ์ ํํ ์ด๋ ์ค์์ ํ ๋น๋์๋์ง๊น์ง ๋ณด์ฌ์ค. ์ด์ ํด๋น ๋ถ๋ถ์ free(message)๋ฅผ ์ถ๊ฐํ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ผ!
Valgrind๊ฐ ์ฐพ์๋ด๋ ๋ค์ํ ์ค๋ฅ๋ค
Valgrind๋ ๋ฉ๋ชจ๋ฆฌ ๋์ ์ธ์๋ ๋ค์ํ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ์ค๋ฅ๋ฅผ ์ฐพ์๋ด. ์ค์ ๋ก ์ด๋ค ์ค๋ฅ๋ค์ ํ์งํ๋์ง ์์ ์ ํจ๊ป ์ดํด๋ณด์:
1. ์๋ชป๋ ๋ฉ๋ชจ๋ฆฌ ์ฝ๊ธฐ/์ฐ๊ธฐ
#include <stdlib.h>
int main() {
int* array = (int*)malloc(10 * sizeof(int));
array[10] = 42; // ๋ฒ์๋ฅผ ๋ฒ์ด๋ ์ ๊ทผ!
free(array);
return 0;
}
Valgrind ์ถ๋ ฅ:
==12346== Invalid write of size 4
==12346== at 0x108654: main (example.c:5)
==12346== Address 0x522d068 is 0 bytes after a block of size 40 alloc'd
2. ์ด๊ธฐํ๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ
#include <stdio.h>
int main() {
int x;
if (x == 10) { // x๊ฐ ์ด๊ธฐํ๋์ง ์์์ด!
printf("x is 10\n");
}
return 0;
}
Valgrind ์ถ๋ ฅ:
==12347== Conditional jump or move depends on uninitialised value(s)
==12347== at 0x108654: main (example.c:5)
3. ์ด์ค ํด์ (Double Free)
#include <stdlib.h>
int main() {
int* ptr = (int*)malloc(sizeof(int));
free(ptr);
free(ptr); // ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ ๋ฒ ํด์ !
return 0;
}
Valgrind ์ถ๋ ฅ:
==12348== Invalid free() / delete / delete[] / realloc()
==12348== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12348== by 0x108668: main (example.c:6)
==12348== Address 0x522d040 is 0 bytes inside a block of size 4 free'd
๐จ GDB์ Valgrind ํจ๊ป ์ฌ์ฉํ๊ธฐ
GDB์ Valgrind๋ ๊ฐ๊ฐ ๊ฐ๋ ฅํ ๋๊ตฌ์ง๋ง, ํจ๊ป ์ฌ์ฉํ๋ฉด ์๋์ง ํจ๊ณผ๊ฐ ์์ฒญ๋! Valgrind๋ก ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ๊ณ , GDB๋ก ์ ํํ ์์ธ์ ํ์ ํ๋ ์์ผ๋ก ์กฐํฉํ ์ ์์ด. ๐ฅ
Valgrind์ GDB ์ฐ๋ํ๊ธฐ
Valgrind๋ GDB ์๋ฒ ๋ชจ๋๋ก ์คํํ ์ ์์ด. ์ด๋ ๊ฒ ํ๋ฉด Valgrind๊ฐ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ์ ๋ GDB๋ก ํ๋ก๊ทธ๋จ ์ํ๋ฅผ ์์ธํ ์ดํด๋ณผ ์ ์์ง:
# ํฐ๋ฏธ๋ 1: Valgrind๋ฅผ GDB ์๋ฒ ๋ชจ๋๋ก ์คํ
valgrind --vgdb=yes --vgdb-error=0 ./myprogram
# ํฐ๋ฏธ๋ 2: GDB๋ฅผ ์คํํ๊ณ Valgrind์ ์ฐ๊ฒฐ
gdb ./myprogram
(gdb) target remote | vgdb
์ด๋ ๊ฒ ํ๋ฉด Valgrind๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ๋ ์๊ฐ GDB๋ก ํ๋ก๊ทธ๋จ์ ์ ์ดํ ์ ์์ด. ๋ณ์ ๊ฐ์ ํ์ธํ๊ณ , ์คํ์ ์ถ์ ํ๊ณ , ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋คํํ ์ ์์ง!
์ค์ ์ํฌํ๋ก์ฐ
์ค์ ๊ฐ๋ฐ์์ ์ด ๋ ๋๊ตฌ๋ฅผ ์ด๋ป๊ฒ ํ์ฉํ๋์ง ๋จ๊ณ๋ณ๋ก ์ดํด๋ณด์:
**1๋จ๊ณ: ์ด๊ธฐ ํ
์คํธ** ๐งช
๋จผ์ ํ๋ก๊ทธ๋จ์ ์ผ๋ฐ์ ์ผ๋ก ์คํํด์ ๋์ ๋ณด์ด๋ ๋ฒ๊ทธ๊ฐ ์๋์ง ํ์ธํด. ์ด ๋จ๊ณ์์ ์ธ๊ทธ๋ฉํ
์ด์
ํดํธ๋ ๋ช
ํํ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ๋ฐ๋ก GDB๋ก ๋์ด๊ฐ.
**2๋จ๊ณ: Valgrind ์ค์บ** ๐
ํ๋ก๊ทธ๋จ์ด ์ ์์ ์ผ๋ก ์คํ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ฌ๋ Valgrind๋ก ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ๋ฅผ ์ฒดํฌํด. ํนํ ๋ฉ๋ชจ๋ฆฌ ๋์๋ ํ๋ก๊ทธ๋จ์ด ์งง๊ฒ ์คํ๋ ๋๋ ๋ฌธ์ ๊ฐ ์ ๋์ง๋ง, ์ค๋ ์คํ๋๋ฉด ์ฌ๊ฐํ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ด.
valgrind --leak-check=full --show-leak-kinds=all \
--track-origins=yes --log-file=valgrind.log ./myprogram
**3๋จ๊ณ: ์ค๋ฅ ๋ถ์** ๐
Valgrind ๋ก๊ทธ๋ฅผ ๋ถ์ํด์ ์ด๋ค ์ข
๋ฅ์ ์ค๋ฅ๊ฐ ์๋์ง ํ์
ํด. "definitely lost"๋ ํ์คํ ๋ฉ๋ชจ๋ฆฌ ๋์๊ณ , "possibly lost"๋ ์ ์ฌ์ ๋ฌธ์ ์ผ.
**4๋จ๊ณ: GDB๋ก ์์ธ ๋๋ฒ๊น
** ๐ฏ
Valgrind๊ฐ ์ง์ ํ ๋ถ๋ถ์ GDB๋ก ์์ธํ ๋ค์ฌ๋ค๋ด. ์ค๋จ์ ์ ์ค์ ํ๊ณ , ๋ณ์ ๊ฐ์ ์ถ์ ํ๋ฉด์ ์ ํํ ์์ธ์ ์ฐพ์๋ด.
**5๋จ๊ณ: ์์ ๋ฐ ์ฌ๊ฒ์ฆ** โ
์ฝ๋๋ฅผ ์์ ํ ํ ๋ค์ Valgrind๋ก ๊ฒ์ฌํด์ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋์ง ํ์ธํด. ํ ๊ฐ์ง ๋ฒ๊ทธ๋ฅผ ๊ณ ์น๋ค๊ฐ ๋ค๋ฅธ ๋ฒ๊ทธ๋ฅผ ๋ง๋ค ์๋ ์์ผ๋๊น!
๐ช ์ค์ ๋๋ฒ๊น ํ๊ณผ ๋ฒ ์คํธ ํ๋ํฐ์ค
์ด๋ก ์ ์ถฉ๋ถํ ๋ฐฐ์ ์ผ๋, ์ด์ ์ค์ ์์ ๋ฐ๋ก ์จ๋จน์ ์ ์๋ ํ๋ค์ ๊ณต์ ํ ๊ฒ! ์ด๊ฑด ๋ด๊ฐ ์๋ ๊ฐ C์ธ์ด๋ก ๊ฐ๋ฐํ๋ฉด์ ํฐ๋ํ ๋ ธํ์ฐ๋ค์ด์ผ. ๐
๋๋ฒ๊น ์ ์ฝ๊ฒ ๋ง๋๋ ์ฝ๋ฉ ์ต๊ด
ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ํญ์ NULL ์ฒดํฌ๋ฅผ ํด:
char* str = get_string();
if (str == NULL) {
fprintf(stderr, "Error: get_string returned NULL\n");
return -1;
}
// ์ด์ ์์ ํ๊ฒ str ์ฌ์ฉ
malloc์ ์ฐ๋ ์๊ฐ ๋ฐ๋ก ๊ทธ ์๋์ ์ฃผ์์ผ๋ก free๋ฅผ ์ด๋์ ํ ์ง ์ ์ด๋ฌ:
char* buffer = (char*)malloc(SIZE);
// TODO: free(buffer) in cleanup_function()
// ... ์ฝ๋ ...
cleanup_function() {
free(buffer);
}
์กฐ๊ฑด๋ถ ์ปดํ์ผ์ ํ์ฉํด์ ๋๋ฒ๊ทธ ์ ๋ณด๋ฅผ ์ฝ๊ฒ ์ผ๊ณ ๋ ์ ์๊ฒ ํด:
#ifdef DEBUG
#define DEBUG_PRINT(fmt, ...) \
fprintf(stderr, "DEBUG %s:%d: " fmt "\n", \
__FILE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...) do {} while(0)
#endif
// ์ฌ์ฉ ์
DEBUG_PRINT("Variable x = %d", x);
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ํจํด
๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ๋ฅผ ์๋ฐฉํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ์ผ๊ด๋ ํจํด์ ๋ฐ๋ฅด๋ ๊ฑฐ์ผ. ๋ค์์ ๊ฒ์ฆ๋ ํจํด๋ค์ด์ผ:
**RAII ์คํ์ผ (Resource Acquisition Is Initialization)** ๐๏ธ
C++์ ๊ฐ๋
์ด์ง๋ง C์์๋ ๋น์ทํ๊ฒ ๊ตฌํํ ์ ์์ด:
typedef struct {
char* data;
size_t size;
} Buffer;
Buffer* buffer_create(size_t size) {
Buffer* buf = (Buffer*)malloc(sizeof(Buffer));
if (buf == NULL) return NULL;
buf->data = (char*)malloc(size);
if (buf->data == NULL) {
free(buf);
return NULL;
}
buf->size = size;
return buf;
}
void buffer_destroy(Buffer* buf) {
if (buf == NULL) return;
free(buf->data);
free(buf);
}
// ์ฌ์ฉ
Buffer* buf = buffer_create(1024);
if (buf != NULL) {
// ๋ฒํผ ์ฌ์ฉ
buffer_destroy(buf); // ๊น๋ํ๊ฒ ์ ๋ฆฌ
}
**์์ ๊ถ ๋ช
ํํ ํ๊ธฐ** ๐
ํจ์๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๋ฉด ๋๊ฐ ํด์ ํ ์ฑ
์์ด ์๋์ง ๋ช
ํํ ํด:
// ํธ์ถ์๊ฐ freeํด์ผ ํจ์ ๋ช
์
// Returns: Newly allocated string (caller must free)
char* create_greeting(const char* name) {
size_t len = strlen("Hello, ") + strlen(name) + 1;
char* greeting = (char*)malloc(len);
if (greeting != NULL) {
sprintf(greeting, "Hello, %s", name);
}
return greeting;
}
์ฑ๋ฅ๊ณผ ๋๋ฒ๊น ์ ๊ท ํ
๋๋ฒ๊น ์ฝ๋๊ฐ ๋๋ฌด ๋ง์ผ๋ฉด ํ๋ก๊ทธ๋จ์ด ๋๋ ค์ง ์ ์์ด. ํ์ง๋ง ์ ์ ํ ๊ท ํ์ ์ฐพ์ผ๋ฉด ๋ ๋ค ์ก์ ์ ์์ง:
-g -O0 (๋๋ฒ๊ทธ ์ ๋ณด ํฌํจ, ์ต์ ํ ์์)์ผ๋ก ์ปดํ์ผํ๊ณ , ๋ฐฐํฌํ ๋๋ -O2 -DNDEBUG (์ต์ ํ ํ์ฑํ, ๋๋ฒ๊ทธ ์ฝ๋ ์ ๊ฑฐ)๋ก ์ปดํ์ผํด. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๋ฐ ์ค์๋ ๋๋ฒ๊น
์ด ์ฝ๊ณ , ๋ฐฐํฌ ๋ฒ์ ์ ๋น ๋ฅด๊ฒ ์คํ๋ผ!
๐ ๊ณ ๊ธ ๋๋ฒ๊น ๊ธฐ๋ฒ
๊ธฐ๋ณธ์ ๋์ด์ ๋ ๊น์ด ๋ค์ด๊ฐ๋ณด์! ์ด๋ฐ ๊ธฐ๋ฒ๋ค์ ์๋ฉด ์ ๋ง ๊น๋ค๋ก์ด ๋ฒ๊ทธ๋ ์ก์ ์ ์์ด. ๐
์ฝ์ด ๋คํ ๋ถ์
ํ๋ก๊ทธ๋จ์ด ํฌ๋์ํ๋ฉด ์ฝ์ด ๋คํ ํ์ผ์ด ์์ฑ๋ผ. ์ด๊ฑด ํ๋ก๊ทธ๋จ์ด ์ฃฝ๋ ์๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ค๋ ์ท์ด์ผ. GDB๋ก ์ด๊ฑธ ๋ถ์ํ ์ ์์ด:
# ์ฝ์ด ๋คํ ํ์ฑํ
ulimit -c unlimited
# ํ๋ก๊ทธ๋จ ์คํ (ํฌ๋์ ๋ฐ์)
./myprogram
# ์ฝ์ด ๋คํ ๋ถ์
gdb ./myprogram core
(gdb) backtrace
(gdb) info registers
(gdb) print variable_name
์ฝ์ด ๋คํ๋ ํนํ ์ฌํํ๊ธฐ ์ด๋ ค์ด ๋ฒ๊ทธ๋ฅผ ๋๋ฒ๊น ํ ๋ ์ ๋ง ์ ์ฉํด. ํ๋ก๊ทธ๋จ์ด ์ฃฝ์ ์๊ฐ์ ๋ชจ๋ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์๊ฑฐ๋ !
๋ฉํฐ์ค๋ ๋ ๋๋ฒ๊น
๋ฉํฐ์ค๋ ๋ ํ๋ก๊ทธ๋จ์ ๋๋ฒ๊น ํ๊ธฐ ์ ๋ง ๊น๋ค๋ก์. ๋ ์ด์ค ์ปจ๋์ ์ด๋ ๋ฐ๋๋ฝ ๊ฐ์ ๋ฌธ์ ๋ค์ ํ์ด๋ฐ์ ๋ฐ๋ผ ๋ฐ์ํ๊ฑฐ๋ ์ ํ๊ฑฐ๋ . GDB๋ ์ค๋ ๋ ๋๋ฒ๊น ์ ์ํ ํน๋ณํ ๋ช ๋ น์ด๋ค์ ์ ๊ณตํด:
(gdb) info threads # ๋ชจ๋ ์ค๋ ๋ ๋ชฉ๋ก
(gdb) thread 2 # ์ค๋ ๋ 2๋ก ์ ํ
(gdb) thread apply all bt # ๋ชจ๋ ์ค๋ ๋์ ๋ฐฑํธ๋ ์ด์ค
(gdb) set scheduler-locking on # ํ์ฌ ์ค๋ ๋๋ง ์คํ
Valgrind์ Helgrind ๋๊ตฌ๋ ์ค๋ ๋ ๊ด๋ จ ์ค๋ฅ๋ฅผ ์ฐพ๋ ๋ฐ ํนํ๋์ด ์์ด:
valgrind --tool=helgrind ./myprogram
Helgrind๋ ๋ฐ์ดํฐ ๋ ์ด์ค, ์๋ชป๋ ๋ฎคํ ์ค ์ฌ์ฉ, ๋ฝ ์์ ๋ฌธ์ ๋ฑ์ ํ์งํด์ค.
ํ๋กํ์ผ๋ง๊ณผ ๋๋ฒ๊น ์ ๊ฒฐํฉ
๋๋ก๋ ๋ฒ๊ทธ๊ฐ ์๋๋ผ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น ํด์ผ ํ ๋๋ ์์ด. Valgrind์ Callgrind ๋๊ตฌ๋ ํ๋ก๊ทธ๋จ์ ์ฑ๋ฅ์ ๋ถ์ํด์ค:
valgrind --tool=callgrind ./myprogram
callgrind_annotate callgrind.out.12345
์ด๋ ๊ฒ ํ๋ฉด ์ด๋ ํจ์๊ฐ ๊ฐ์ฅ ๋ง์ด ํธ์ถ๋๊ณ , ์ด๋์ ์๊ฐ์ ๋ง์ด ์ฐ๋์ง ์ ์ ์์ด. KCachegrind ๊ฐ์ GUI ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์๊ฐ์ ์ผ๋ก ๋ถ์ํ ์๋ ์์ง!
๐ฏ ์ค๋ฌด์์์ ๋๋ฒ๊น ์ ๋ต
์ด๋ก ๊ณผ ๋๊ตฌ๋ฅผ ์๋ ๊ฒ๋ ์ค์ํ์ง๋ง, ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ์ ์ฉํ๋์ง๊ฐ ๋ ์ค์ํด. ์ค๋ฌด ๊ฒฝํ์ ๋ฐํ์ผ๋ก ํจ๊ณผ์ ์ธ ๋๋ฒ๊น ์ ๋ต์ ๊ณต์ ํ ๊ฒ! ๐ผ
๋ฒ๊ทธ ์ฌํ ๊ฐ๋ฅ์ฑ ํ๋ณด
๋๋ฒ๊น ์ ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ๋ฒ๊ทธ๋ฅผ ์์ ์ ์ผ๋ก ์ฌํํ๋ ๊ฑฐ์ผ. ์ฌํํ ์ ์๋ ๋ฒ๊ทธ๋ ๊ณ ์น ์ ์๊ฑฐ๋ ! ๋ค์ ์ ๋ณด๋ค์ ๊ธฐ๋กํด๋ฌ:
- ์ ํํ ์
๋ ฅ ๋ฐ์ดํฐ
- ์คํ ํ๊ฒฝ (OS, ์ปดํ์ผ๋ฌ ๋ฒ์ , ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ )
- ์คํ ์์์ ํ์ด๋ฐ
- ์๋ฌ ๋ฉ์์ง์ ๋ก๊ทธ
// ์ฌํ ๊ฐ๋ฅํ ํ
์คํธ ์ผ์ด์ค ์์ฑ
void test_buffer_overflow() {
char buffer[10];
const char* input = "This is too long";
// ๋ฒ๊ทธ ์ฌํ
strcpy(buffer, input); // ์ฌ๊ธฐ์ ์ค๋ฒํ๋ก์ฐ ๋ฐ์
// ์์ ๊ฒฐ๊ณผ vs ์ค์ ๊ฒฐ๊ณผ ๊ธฐ๋ก
printf("Expected: Safe copy\n");
printf("Actual: Buffer overflow\n");
}
์ด์ง ํ์ ๋๋ฒ๊น
ํฐ ํ๋ก์ ํธ์์ ๋ฒ๊ทธ์ ์์น๋ฅผ ๋ชจ๋ฅผ ๋๋ ์ด์ง ํ์ ๋ฐฉ์์ ์จ. ์ฝ๋์ ์ค๊ฐ ์ง์ ์ ๋ก๊ทธ๋ฅผ ์ฐ์ด์ ๋ฒ๊ทธ๊ฐ ๊ทธ ์ ์ ๋ฐ์ํ๋์ง ํ์ ๋ฐ์ํ๋์ง ํ์ธํ๊ณ , ๋ฒ์๋ฅผ ์ ๋ฐ์ฉ ์ขํ๊ฐ๋ ๊ฑฐ์ผ:
void complex_function() {
// ์์
DEBUG_PRINT("Starting complex_function");
step1();
DEBUG_PRINT("After step1"); // ์ฌ๊ธฐ๊น์ง๋ ์ ์
step2();
DEBUG_PRINT("After step2"); // ์ฌ๊ธฐ์ ๋ฌธ์ ๋ฐ์!
step3();
DEBUG_PRINT("After step3");
}
ํ๊ท ํ ์คํธ ์๋ํ
๋ฒ๊ทธ๋ฅผ ๊ณ ์ณค์ผ๋ฉด ๊ฐ์ ๋ฒ๊ทธ๊ฐ ๋ค์ ๋ฐ์ํ์ง ์๋๋ก ํ ์คํธ๋ฅผ ์๋ํํด. ๊ฐ๋จํ ์คํฌ๋ฆฝํธ๋ก๋ ์ถฉ๋ถํด:
#!/bin/bash
# test_memory.sh
echo "Running memory tests..."
# Valgrind๋ก ๋ฉ๋ชจ๋ฆฌ ํ
์คํธ
valgrind --leak-check=full --error-exitcode=1 ./myprogram test_input.txt
if [ $? -eq 0 ]; then
echo "โ
Memory test passed"
else
echo "โ Memory test failed"
exit 1
fi
# ์ถ๊ฐ ํ
์คํธ๋ค...
./myprogram test1.txt
./myprogram test2.txt
./myprogram test3.txt
echo "All tests completed!"
๐ ์ฌ๋ฅ๋ท์์ ๋๋ฒ๊น ์คํฌ ๊ณต์ ํ๊ธฐ
๋๋ฒ๊น ์ ์ ๋ง ๊ฐ์น ์๋ ๊ธฐ์ ์ด์ผ. ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๋๋ฒ๊น ์ ์ด๋ ค์์ ๊ฒช๊ณ ์๊ณ , ์ด๋ฐ ๊ธฐ์ ์ ๋ฐฐ์ฐ๊ณ ์ถ์ด ํด. ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์๋ ์ด๋ฐ ์ ๋ฌธ ์ง์์ ๊ณต์ ํ๊ณ ์์ต์ ์ฐฝ์ถํ ์๋ ์์ด! ๐
์๋ฅผ ๋ค์ด, "C์ธ์ด ๋ฉ๋ชจ๋ฆฌ ๋๋ฒ๊น 1:1 ์ฝ์นญ", "Valgrind ์ค์ ํ์ฉ๋ฒ", "๋ณต์กํ ๋ฒ๊ทธ ํด๊ฒฐ ์ปจ์คํ " ๊ฐ์ ์ฌ๋ฅ์ ๋ฑ๋กํ ์ ์์ง. ์ค์ ๋ก ๋ง์ ๊ฐ๋ฐ์๋ค์ด ํน์ ๋ฒ๊ทธ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ํ์ํด์ ์ ๋ฌธ๊ฐ์ ์กฐ์ธ์ ๊ตฌํ๊ณค ํด. ๋์ ๋๋ฒ๊น ๋ ธํ์ฐ๊ฐ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ๋ ์ ๋ง ๊ท์คํ ์์ฐ์ด ๋ ์ ์์ด!
๋ํ ์ฌ๋ฅ๋ท์์ ๋ค๋ฅธ ์ ๋ฌธ๊ฐ๋ค์ ๋๋ฒ๊น ํ์ ๋ฐฐ์ธ ์๋ ์์ด. ํผ์ ๊ณ ๋ฏผํ๋ ๊ฒ๋ณด๋ค ๊ฒฝํ ๋ง์ ๊ฐ๋ฐ์์๊ฒ ๋ฐฐ์ฐ๋ฉด ํจ์ฌ ๋น ๋ฅด๊ฒ ์ฑ์ฅํ ์ ์๊ฑฐ๋ . ํนํ ์ค๋ฌด์์ ๋ง์ฃผ์น๋ ๋ณต์กํ ๋ฌธ์ ๋ค์ ์ฑ ์ด๋ ๋ฌธ์๋ง์ผ๋ก๋ ํด๊ฒฐํ๊ธฐ ์ด๋ ค์ธ ๋๊ฐ ๋ง์. ๊ทธ๋ด ๋ ์ค์ ๊ฒฝํ์ด ํ๋ถํ ๋ฉํ ์ ๋์์ ๋ฐ์ผ๋ฉด ์ ๋ง ํฐ ๋์์ด ๋ผ! ๐ช
๐ ์ถ๊ฐ ํ์ต ๋ฆฌ์์ค์ ๋๊ตฌ๋ค
GDB์ Valgrind ์ธ์๋ ์์๋๋ฉด ์ข์ ๋๊ตฌ๋ค๊ณผ ๋ฆฌ์์ค๋ฅผ ์๊ฐํ ๊ฒ:
์ ์ฉํ ๋๋ฒ๊น ๋๊ตฌ๋ค
**AddressSanitizer (ASan)** ๐ฌ
๊ตฌ๊ธ์ด ๊ฐ๋ฐํ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ ํ์ง ๋๊ตฌ์ผ. Valgrind๋ณด๋ค ๋น ๋ฅด๊ณ (2~3๋ฐฐ ๋๋ฆผ vs 10~50๋ฐฐ ๋๋ฆผ), ์ปดํ์ผ ํ์์ ํตํฉ๋ผ:
gcc -fsanitize=address -g -o myprogram myprogram.c
./myprogram
**UndefinedBehaviorSanitizer (UBSan)** โก
์ ์๋์ง ์์ ๋์(undefined behavior)์ ์ฐพ์๋ด๋ ๋๊ตฌ์ผ:
gcc -fsanitize=undefined -g -o myprogram myprogram.c
**Electric Fence** ๐
๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ๋ฅผ ์ฆ์ ํ์งํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ๊ฐ malloc ํธ์ถ๋ง๋ค ๋ณดํธ ํ์ด์ง๋ฅผ ํ ๋นํด์ ์ค๋ฒํ๋ก์ฐ๋ฅผ ์ฆ์ ์ก์๋ด:
gcc -o myprogram myprogram.c -lefence
./myprogram
๋๋ฒ๊น ํ์ต ์๋ฃ
- **GDB ๊ณต์ ๋ฌธ์**: ๊ฐ์ฅ ๊ถ์ ์๋ ์๋ฃ. ๋ชจ๋ ๋ช
๋ น์ด์ ๊ธฐ๋ฅ์ด ์์ธํ ์ค๋ช
๋์ด ์์ด.
- **Valgrind ์ฌ์ฉ์ ๋งค๋ด์ผ**: Valgrind์ ๋ชจ๋ ๋๊ตฌ์ ์ต์
์ ๋ค๋ฃจ๋ ์๋ฒฝํ ๊ฐ์ด๋.
- **"The Art of Debugging with GDB, DDD, and Eclipse"**: ์ค์ ๋๋ฒ๊น
๊ธฐ๋ฒ์ ๋ค๋ฃจ๋ ํ๋ฅญํ ์ฑ
.
- **"Effective Debugging"**: 66๊ฐ์ง ๋๋ฒ๊น
์ ๋ต์ ์๊ฐํ๋ ์ค์ฉ์ ์ธ ์ฑ
.
๐ฌ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์! ์ฌ๊ธฐ๊น์ง ์ ๋ง ๊ธด ์ฌ์ ์ด์์ด. ๐ C์ธ์ด ๋๋ฒ๊น ๊ณผ GDB, Valgrind์ ๋ํด ์ ๋ง ๋ง์ ๊ฑธ ๋ค๋ค์ง? ์ฒ์์๋ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ํ๋์ฉ ์ค์ตํ๋ค ๋ณด๋ฉด ๊ธ๋ฐฉ ์ต์ํด์ง ๊ฑฐ์ผ.
๋๋ฒ๊น ์ ๋จ์ํ ๋ฒ๊ทธ๋ฅผ ์ฐพ๋ ๊ฒ ์ด์์ ์๋ฏธ๊ฐ ์์ด. ์ฝ๋๋ฅผ ๊น์ด ์ดํดํ๊ณ , ํ๋ก๊ทธ๋จ์ ๋์ ์๋ฆฌ๋ฅผ ํ์ ํ๊ณ , ๋ ๋์ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋๋ ๊ณผ์ ์ด์ผ. ๋ฒ๊ทธ๋ฅผ ๋ง๋๋ฉด ์ข์ ํ์ง ๋ง๊ณ , ์คํ๋ ค ๋ฐฐ์ธ ๊ธฐํ๋ผ๊ณ ์๊ฐํด! ๐
๊ธฐ์ตํด, ๋ชจ๋ ํ๋ฅญํ ํ๋ก๊ทธ๋๋จธ๋ค๋ ์ฒ์์๋ ์ด๋ณด์๊ณ , ์๋ง์ ๋ฒ๊ทธ์ ์จ๋ฆํ๋ฉด์ ์ฑ์ฅํ์ด. ๋๋ ์ถฉ๋ถํ ํ ์ ์์ด! GDB์ Valgrind๋ฅผ ๋ง์คํฐํ๋ฉด C์ธ์ด ๊ฐ๋ฐ์ด ํจ์ฌ ์ฆ๊ฑฐ์์ง ๊ฑฐ์ผ. ํ์ดํ ! ๐
์ด์ ๋๋ C์ธ์ด ๋๋ฒ๊น ์ ํต์ฌ ๋๊ตฌ๋ค์ ์๊ฒ ๋์์ด. GDB๋ก ํ๋ก๊ทธ๋จ์ ์คํ์ ์ถ์ ํ๊ณ , Valgrind๋ก ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ๋ฅผ ์ฐพ์๋ด๊ณ , ๋ค์ํ ๋๋ฒ๊น ๊ธฐ๋ฒ์ผ๋ก ๋ณต์กํ ๋ฒ๊ทธ๋ ํด๊ฒฐํ ์ ์๊ฒ ๋์์ง. ์ด ์ง์์ ๋ฐํ์ผ๋ก ๋ ์์ ์ ์ด๊ณ ํจ์จ์ ์ธ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ด! ๐
ํ๋ณตํ ์ฝ๋ฉ, ๊ทธ๋ฆฌ๊ณ ์ฑ๊ณต์ ์ธ ๋๋ฒ๊น ๋๊ธธ ๋ฐ๋ผ! ๐โจ
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.