์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ› ๏ธ Valgrind๋กœ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์žก์•„๋‚ด๊ธฐ ๐Ÿ”

๐Ÿ› ๏ธ Valgrind๋กœ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์žก์•„๋‚ด๊ธฐ ๐Ÿ”

C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ˆจ์€ ์ , ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜์™€์˜ ์ „์Ÿ

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ C ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•  ๋•Œ ์ง„์งœ ๊ณจ์น˜ ์•„ํ”ˆ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜๋ฅผ ์ฐพ์•„๋‚ด๋Š” ์ดˆ๊ฐ•๋ ฅ ๋„๊ตฌ์ธ Valgrind์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”! ๐Ÿ˜Ž

C ์–ธ์–ด๋กœ ์ฝ”๋”ฉํ•˜๋‹ค ๋ณด๋ฉด ์ด๋Ÿฐ ๊ฒฝํ—˜ ์žˆ์œผ์‹œ์ฃ ? ํ”„๋กœ๊ทธ๋žจ์ด ๊ฐ‘์ž๊ธฐ '์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜ ์˜ค๋ฅ˜'๋ผ๋ฉด์„œ ๋ป—์–ด๋ฒ„๋ฆฌ๊ฑฐ๋‚˜, ์•„๋‹ˆ๋ฉด ๋” ๋ฌด์„œ์šด ๊ฑด ๊ฒ‰์œผ๋กœ๋Š” ๋ฉ€์ฉกํ•œ๋ฐ ๋’ค์—์„œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ƒˆ๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ... ์ง„์งœ ์ฐพ๊ธฐ ์–ด๋ ต์ฃ ? ใ… ใ… 

๊ทผ๋ฐ ๊ฑฑ์ • ๋งˆ์„ธ์š”! Valgrind๋ผ๋Š” ์—„์ฒญ๋‚œ ์นœ๊ตฌ๊ฐ€ ์žˆ์–ด์š”. ์ด ๋„๊ตฌ๋Š” ๋งˆ์น˜ ๋ฉ”๋ชจ๋ฆฌ ์„ธ๊ณ„์˜ CCTV ๊ฐ™์•„์„œ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๋‹ค ์ง€์ผœ๋ณด๊ณ  ์žˆ๋‹ต๋‹ˆ๋‹ค. ๐Ÿ‘€

์ด ๊ธ€์—์„œ๋Š” Valgrind๊ฐ€ ๋ญ”์ง€, ์–ด๋–ป๊ฒŒ ์„ค์น˜ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜๋“ค์„ ์žก์•„๋‚ผ ์ˆ˜ ์žˆ๋Š”์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ํŠนํžˆ C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๋ฐฐ์šฐ๋Š” ๋ถ„๋“ค์ด๋‚˜ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค์—๊ฒŒ ๊ผญ ํ•„์š”ํ•œ ๋‚ด์šฉ์ด๋‹ˆ ๋๊นŒ์ง€ ํ•จ๊ป˜ํ•ด์š”! ๐Ÿš€

๐Ÿ“š ๋ชฉ์ฐจ

  1. Valgrind๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?
  2. Valgrind ์„ค์น˜ํ•˜๊ธฐ
  3. Valgrind ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•
  4. ์ฃผ์š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์œ ํ˜•๊ณผ ํ•ด๊ฒฐ๋ฒ•
  5. Valgrind ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ์‚ดํŽด๋ณด๊ธฐ
  6. ์‹ค์ „ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” Valgrind
  7. ์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ๋“ค

1. Valgrind๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? ๐Ÿค”

Valgrind๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜์™€ ๋ˆ„์ˆ˜๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์˜ˆ์š”. 2000๋…„๋Œ€ ์ดˆ๋ฐ˜์— ๋“ฑ์žฅํ•ด์„œ ์ง€๊ธˆ๊นŒ์ง€ C/C++ ๊ฐœ๋ฐœ์ž๋“ค์˜ ํ•„์ˆ˜ ๋„๊ตฌ๋กœ ์ž๋ฆฌ์žก์•˜์ฃ . ์ด๋ฆ„์ด ์ข€ ํŠน์ดํ•˜์ฃ ? ๋ถ์œ ๋Ÿฝ ์‹ ํ™”์—์„œ ์˜๊ฐ์„ ๋ฐ›์•˜๋‹ค๊ณ  ํ•ด์š”! ใ…‹ใ…‹ใ…‹

Valgrind์˜ ๊ฐ€์žฅ ์œ ๋ช…ํ•œ ๊ธฐ๋Šฅ์€ Memcheck์ธ๋ฐ์š”, ์ด๊ฒŒ ๋ฐ”๋กœ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ จ ๋ฌธ์ œ๋ฅผ ์ฐพ์•„๋‚ด๋Š” ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ด์—์š”. ๊ทธ ์™ธ์—๋„ ์บ์‹œ ๋ฏธ์Šค, ์Šค๋ ˆ๋“œ ๋ฌธ์ œ ๋“ฑ์„ ๋ถ„์„ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋„๊ตฌ๋“ค์ด ์žˆ์–ด์š”.

Valgrind์˜ ์ฃผ์š” ๊ธฐ๋Šฅ Memcheck ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ๊ฒ€์ถœ Cachegrind ์บ์‹œ ๋ถ„์„ Callgrind ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ถ„์„ Helgrind ์Šค๋ ˆ๋“œ ์˜ค๋ฅ˜ ๊ฒ€์ถœ Massif ํž™ ํ”„๋กœํŒŒ์ผ๋ง DRD ๋ฐ์ดํ„ฐ ๋ ˆ์ด์Šค ๊ฒ€์ถœ DHAT ํž™ ์‚ฌ์šฉ๋Ÿ‰ ๋ถ„์„

Valgrind๊ฐ€ ๋Œ€์ฒด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๊ฑธ๊นŒ์š”? ๐Ÿง ๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ€์ƒ CPU ์œ„์—์„œ ์‹คํ–‰์‹œํ‚ค๋ฉด์„œ ๋ชจ๋“  ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์„ ๊ฐ์‹œํ•ด์š”. ๊ทธ๋ž˜์„œ ์ข€ ๋А๋ฆฌ๊ธด ํ•˜์ง€๋งŒ(์›๋ž˜ ์†๋„์˜ ์•ฝ 10~30๋ฐฐ), ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ์–ด์š”!

์š”์ฆ˜ ๊ฐ™์€ ์‹œ๋Œ€์— ๊ฐœ๋ฐœ์ž๋กœ ์„ฑ์žฅํ•˜๋ ค๋ฉด ์ด๋Ÿฐ ๋„๊ตฌ๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ๋ฐ์š”, ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋„ Valgrind ๊ฐ™์€ ๋„๊ตฌ ํ™œ์šฉ๋ฒ•์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋Š” ๊ฐ•์˜๋“ค์ด ์ธ๊ธฐ๊ฐ€ ๋งŽ๋”๋ผ๊ณ ์š”. ๊ฐœ๋ฐœ์ž์˜ ์‹ค๋ ฅ์„ ํ•œ ๋‹จ๊ณ„ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋˜๋‹ˆ๊นŒ์š”! ๐Ÿ’ช

2. Valgrind ์„ค์น˜ํ•˜๊ธฐ ๐Ÿ”ง

์ž, ์ด์ œ Valgrind๋ฅผ ์„ค์น˜ํ•ด๋ณผ๊นŒ์š”? ์šด์˜์ฒด์ œ๋ณ„๋กœ ์„ค์น˜ ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅด๋‹ˆ ํ™•์ธํ•ด๋ณด์„ธ์š”!

Linux์—์„œ ์„ค์น˜ํ•˜๊ธฐ ๐Ÿง

๋ฆฌ๋ˆ…์Šค๋Š” Valgrind์˜ ๊ณ ํ–ฅ์ด๋ผ ์„ค์น˜๊ฐ€ ์ดˆ๊ฐ„๋‹จ์ด์—์š”!

Ubuntu/Debian:

sudo apt-get install valgrind

Fedora/RHEL/CentOS:

sudo dnf install valgrind

Arch Linux:

sudo pacman -S valgrind

macOS์—์„œ ์„ค์น˜ํ•˜๊ธฐ ๐ŸŽ

๋งฅ์—์„œ๋Š” Homebrew๋ฅผ ์ด์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์–ด์š”:

brew install valgrind

โš ๏ธ ์ฃผ์˜: ์ตœ์‹  macOS ๋ฒ„์ „์—์„œ๋Š” Valgrind๊ฐ€ ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์–ด์š”. ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด Docker๋‚˜ ๊ฐ€์ƒ๋จธ์‹ ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๋ฐฉ๋ฒ•์ด์—์š”!

Windows์—์„œ ์„ค์น˜ํ•˜๊ธฐ ๐ŸชŸ

์œˆ๋„์šฐ์—์„œ๋Š” ์ง์ ‘ ์ง€์›์ด ์•ˆ ๋˜์ง€๋งŒ, ๋‹ค์Œ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:

  1. WSL(Windows Subsystem for Linux) ์„ค์น˜
  2. WSL์—์„œ Ubuntu ๋“ฑ์˜ ๋ฆฌ๋ˆ…์Šค ๋ฐฐํฌํŒ ์„ค์น˜
  3. ๋ฆฌ๋ˆ…์Šค ๋ฐฐํฌํŒ ๋‚ด์—์„œ Valgrind ์„ค์น˜

๋˜๋Š” Cygwin์ด๋‚˜ MinGW ํ™˜๊ฒฝ์—์„œ ์‹œ๋„ํ•ด๋ณผ ์ˆ˜๋„ ์žˆ์–ด์š”.

์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ์ œ๋Œ€๋กœ ์„ค์น˜๋๋Š”์ง€ ํ™•์ธํ•ด๋ณด์„ธ์š”:

valgrind --version

๋ฒ„์ „ ์ •๋ณด๊ฐ€ ๋‚˜์˜ค๋ฉด ์„ฑ๊ณต์ž…๋‹ˆ๋‹ค! ๐ŸŽ‰ ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Valgrind๋ฅผ ์‚ฌ์šฉํ•ด๋ณผ ์ค€๋น„๊ฐ€ ๋์–ด์š”!

3. Valgrind ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ๐Ÿ“

์ž, ์ด์ œ Valgrind๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ๊ฒŒ์š”! ์ง„์งœ ์‰ฌ์›Œ์š”, ๊ฑฑ์ • ๋งˆ์„ธ์š”~ ใ…Žใ…Ž

๊ธฐ๋ณธ ๋ช…๋ น์–ด ๊ตฌ์กฐ

Valgrind์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์€ ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ์–ด์š”:

valgrind [valgrind-์˜ต์…˜] [ํ”„๋กœ๊ทธ๋žจ] [ํ”„๋กœ๊ทธ๋žจ-์ธ์ž]

๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” Memcheck ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๋ช…๋ น์–ด๋Š” ์ด๋ ‡์Šต๋‹ˆ๋‹ค:

valgrind --tool=memcheck [ํ”„๋กœ๊ทธ๋žจ]

์‚ฌ์‹ค memcheck๋Š” ๊ธฐ๋ณธ ๋„๊ตฌ๋ผ์„œ ์ƒ๋žตํ•ด๋„ ๋ผ์š”:

valgrind [ํ”„๋กœ๊ทธ๋žจ]

๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋กœ ์‹œ์ž‘ํ•ด๋ณด๊ธฐ

๋จผ์ € ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ C ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”:

// memory_error.c
#include <stdlib.h>

int main() {
    int *x = malloc(10 * sizeof(int));
    x[10] = 0;  // ๋ฐฐ์—ด ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ์ ‘๊ทผ! ํ• ๋‹น๋œ ํฌ๊ธฐ๋Š” 0~9๊นŒ์ง€์ธ๋ฐ 10์— ์ ‘๊ทผ
    
    // ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๋ฅผ ์•ˆ ํ•จ (๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜)
    return 0;
}

์ด ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผํ•˜๊ณ  Valgrind๋กœ ์‹คํ–‰ํ•ด๋ณผ๊ฒŒ์š”:

gcc -g memory_error.c -o memory_error
valgrind ./memory_error

-g ์˜ต์…˜์€ ๋””๋ฒ„๊น… ์ •๋ณด๋ฅผ ํฌํ•จํ•ด์„œ ์ปดํŒŒ์ผํ•˜๋ผ๋Š” ์˜๋ฏธ์˜ˆ์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Valgrind๊ฐ€ ๋” ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์ค˜์š”!

์‹คํ–‰ํ•˜๋ฉด ๋Œ€๋žต ์ด๋Ÿฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ๊ฑฐ์˜ˆ์š”:

==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...
==12345== Command: ./memory_error
==12345== 
==12345== Invalid write of size 4
==12345==    at 0x109177: main (memory_error.c:5)
==12345==  Address 0x4a37068 is 0 bytes after a block of size 40 alloc'd
==12345==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12345==    by 0x109166: main (memory_error.c:4)
==12345== 
==12345== HEAP SUMMARY:
==12345==     in use at exit: 40 bytes in 1 blocks
==12345==   total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==12345== 
==12345== LEAK SUMMARY:
==12345==    definitely lost: 40 bytes in 1 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: 2 errors from 2 contexts (suppressed: 0 from 0)

์šฐ์™€! ๐Ÿ˜ฒ Valgrind๊ฐ€ ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ์ฐพ์•„๋ƒˆ์–ด์š”:

  1. Invalid write: ๋ฐฐ์—ด ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ์ ‘๊ทผ (x[10])
  2. Memory leak: malloc์œผ๋กœ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ freeํ•˜์ง€ ์•Š์Œ

์ด๋ ‡๊ฒŒ Valgrind๋Š” ์‹คํ–‰ ์ค‘์— ๋ฐœ์ƒํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜๋ฅผ ์ •ํ™•ํžˆ ์•Œ๋ ค์ฃผ๊ณ , ์–ด๋А ์ฝ”๋“œ ๋ผ์ธ์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€๊นŒ์ง€ ์•Œ๋ ค์ค˜์š”! ์ง„์งœ ๊ฐœ๋ฐœ์ž์˜ ๊ตฌ์„ธ์ฃผ ์•„๋‹ˆ๊ฒ ์–ด์š”? ใ…‹ใ…‹ใ…‹

์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์˜ต์…˜๋“ค

Valgrind๋ฅผ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์šฉํ•œ ์˜ต์…˜๋“ค์ด์—์š”:

--leak-check=full: ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ •๋ณด ์ œ๊ณต

--show-leak-kinds=all: ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ํ‘œ์‹œ

--track-origins=yes: ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๊ฐ’์˜ ์ถœ์ฒ˜ ์ถ”์ 

--verbose: ๋” ์ž์„ธํ•œ ์ถœ๋ ฅ

--log-file=ํŒŒ์ผ๋ช…: ๊ฒฐ๊ณผ๋ฅผ ํŒŒ์ผ๋กœ ์ €์žฅ

์ด ์˜ต์…˜๋“ค์„ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋” ์ž์„ธํ•œ ๋ถ„์„์ด ๊ฐ€๋Šฅํ•ด์š”:

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./memory_error

์ด๋Ÿฐ ์‹์œผ๋กœ Valgrind๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๊ฐ€์žฅ ๊นŒ๋‹ค๋กœ์šด ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๋“ค์„ ์‰ฝ๊ฒŒ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ์–ด์š”! ๐Ÿ˜„

4. ์ฃผ์š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์œ ํ˜•๊ณผ ํ•ด๊ฒฐ๋ฒ• ๐Ÿšจ

C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋Š” ์ฃผ์š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์œ ํ˜•๋“ค๊ณผ Valgrind๊ฐ€ ์–ด๋–ป๊ฒŒ ์ด๋ฅผ ์ฐพ์•„๋‚ด๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณผ๊ฒŒ์š”!

์ฃผ์š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์œ ํ˜• ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜์ง€ ์•Š์Œ free() ํ˜ธ์ถœ ๋ˆ„๋ฝ ์ž˜๋ชป๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ๋ฐฐ์—ด ๋ฒ”์œ„ ์ดˆ๊ณผ NULL ํฌ์ธํ„ฐ ์—ญ์ฐธ์กฐ ํ•ด์ œ๋œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™” ์—†์ด ๊ฐ’ ์ฝ๊ธฐ ์‹œ๋„ ์“ฐ๋ ˆ๊ธฐ๊ฐ’ ์‚ฌ์šฉ ์ด์ค‘ ํ•ด์ œ ์ด๋ฏธ ํ•ด์ œ๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‹ค์‹œ free() ํ˜ธ์ถœ Double free ์˜ค๋ฅ˜ ์ž˜๋ชป๋œ ํ• ๋‹น/ํ•ด์ œ ์Œ malloc() โ†’ delete new โ†’ free() ์ž˜๋ชป๋œ ์กฐํ•ฉ ์‚ฌ์šฉ ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์ง€์—ญ ๋ณ€์ˆ˜ ๊ณต๊ฐ„ ์ดˆ๊ณผ ๋ฌดํ•œ ์žฌ๊ท€ ํ˜ธ์ถœ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ

1. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ (Memory Leak) ๐Ÿ’ง

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋Š” ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜์ง€ ์•Š์•„ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์˜ˆ์š”. ํ”„๋กœ๊ทธ๋žจ์ด ์˜ค๋ž˜ ์‹คํ–‰๋ ์ˆ˜๋ก ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ค„์–ด๋“ค์–ด ๊ฒฐ๊ตญ ์‹œ์Šคํ…œ ์„ฑ๋Šฅ ์ €ํ•˜๋‚˜ ํ”„๋กœ๊ทธ๋žจ ์ถฉ๋Œ์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”.

์˜ˆ์ œ ์ฝ”๋“œ:

void memory_leak_example() {
    int *array = malloc(100 * sizeof(int));
    // ์—ฌ๊ธฐ์„œ array ์‚ฌ์šฉ
    
    // free(array); // ์ด ์ค„์ด ์—†์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ!
    return;
}

Valgrind ์ถœ๋ ฅ:

==12345== HEAP SUMMARY:
==12345==     in use at exit: 400 bytes in 1 blocks
==12345==   total heap usage: 1 allocs, 0 frees, 400 bytes allocated
==12345== 
==12345== LEAK SUMMARY:
==12345==    definitely lost: 400 bytes in 1 blocks

ํ•ด๊ฒฐ์ฑ…: ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋ฐ˜๋“œ์‹œ free()๋กœ ํ•ด์ œํ•ด์ฃผ์„ธ์š”! ํŠนํžˆ ํ•จ์ˆ˜๋ฅผ ๋น ์ ธ๋‚˜๊ฐ€๊ธฐ ์ „์— ํ•ด์ œํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.

2. ์ž˜๋ชป๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ (Invalid Memory Access) ๐Ÿšซ

๋ฐฐ์—ด ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๊ฑฐ๋‚˜, ์ด๋ฏธ ํ•ด์ œ๋œ ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜, NULL ํฌ์ธํ„ฐ๋ฅผ ์—ญ์ฐธ์กฐํ•  ๋•Œ ๋ฐœ์ƒํ•ด์š”. ์ด๋Ÿฐ ์˜ค๋ฅ˜๋Š” ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜ ์˜ค๋ฅ˜(Segmentation Fault)๋ฅผ ์ผ์œผํ‚ค๋Š” ์ฃผ๋ฒ”์ด์—์š”!

์˜ˆ์ œ ์ฝ”๋“œ:

void invalid_access_example() {
    int *array = malloc(5 * sizeof(int));
    
    array[5] = 10;  // ์˜ค๋ฅ˜! ์ธ๋ฑ์Šค๋Š” 0~4๊นŒ์ง€๋งŒ ์œ ํšจ
    
    free(array);
    array[0] = 5;   // ์˜ค๋ฅ˜! ์ด๋ฏธ ํ•ด์ œ๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ
    
    int *ptr = NULL;
    *ptr = 10;      // ์˜ค๋ฅ˜! NULL ํฌ์ธํ„ฐ ์—ญ์ฐธ์กฐ
}

Valgrind ์ถœ๋ ฅ:

==12345== Invalid write of size 4
==12345==    at 0x109177: invalid_access_example (example.c:4)
==12345==  Address 0x4a37054 is 0 bytes after a block of size 20 alloc'd

ํ•ด๊ฒฐ์ฑ…: ํ•ญ์ƒ ๋ฐฐ์—ด ๋ฒ”์œ„๋ฅผ ํ™•์ธํ•˜๊ณ , ํฌ์ธํ„ฐ๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธํ•˜์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ํ•ด์ œ๋œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ์ ˆ๋Œ€ ์ ‘๊ทผํ•˜์ง€ ๋งˆ์„ธ์š”!

3. ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ (Uninitialized Memory) โ“

๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•˜๋ฉด ์“ฐ๋ ˆ๊ธฐ๊ฐ’์ด ๋“ค์–ด์žˆ์–ด ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ๋™์ž‘์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”.

์˜ˆ์ œ ์ฝ”๋“œ:

void uninitialized_memory_example() {
    int x;
    if(x > 10) {  // ์˜ค๋ฅ˜! x๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์Œ
        printf("x is greater than 10\n");
    }
    
    int *array = malloc(5 * sizeof(int));
    // array ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š์Œ
    printf("First element: %d\n", array[0]);  // ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๊ฐ’ ์‚ฌ์šฉ
    
    free(array);
}

Valgrind ์ถœ๋ ฅ:

==12345== Conditional jump or move depends on uninitialised value(s)
==12345==    at 0x109177: uninitialized_memory_example (example.c:3)
==12345== 
==12345== Use of uninitialised value of size 8
==12345==    at 0x109190: uninitialized_memory_example (example.c:8)

ํ•ด๊ฒฐ์ฑ…: ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ํ•ญ์ƒ ์ดˆ๊ธฐํ™”ํ•˜์„ธ์š”! malloc()์œผ๋กœ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ์ž๋™์œผ๋กœ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์œผ๋‹ˆ ํ•„์š”ํ•˜๋‹ค๋ฉด memset()์ด๋‚˜ calloc()์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

4. ์ด์ค‘ ํ•ด์ œ (Double Free) ๐Ÿ”„

์ด๋ฏธ ํ•ด์ œํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‹ค์‹œ ํ•ด์ œํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜์˜ˆ์š”.

์˜ˆ์ œ ์ฝ”๋“œ:

void double_free_example() {
    int *ptr = malloc(sizeof(int));
    *ptr = 10;
    
    free(ptr);
    free(ptr);  // ์˜ค๋ฅ˜! ์ด๋ฏธ ํ•ด์ œ๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‹ค์‹œ ํ•ด์ œ
}

Valgrind ์ถœ๋ ฅ:

==12345== Invalid free() / delete / delete[] / realloc()
==12345==    at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12345==    by 0x109177: double_free_example (example.c:6)
==12345==  Address 0x4a37040 is 0 bytes inside a block of size 4 free'd

ํ•ด๊ฒฐ์ฑ…: ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•œ ํ›„์—๋Š” ํฌ์ธํ„ฐ๋ฅผ NULL๋กœ ์„ค์ •ํ•˜๊ณ , free()๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— NULL ์ฒดํฌ๋ฅผ ํ•˜์„ธ์š”.

if (ptr != NULL) {
    free(ptr);
    ptr = NULL;
}

์ด๋Ÿฐ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜๋“ค์€ C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์ •๋ง ํ”ํ•˜๊ฒŒ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, Valgrind ๊ฐ™์€ ๋„๊ตฌ ์—†์ด๋Š” ์ฐพ๊ธฐ๊ฐ€ ์ •๋ง ์–ด๋ ค์›Œ์š”. ํŠนํžˆ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋”๋”์šฑ์š”! ๊ทธ๋ž˜์„œ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๊ณณ์—์„œ C ์–ธ์–ด ๊ฐ•์˜๋ฅผ ๋“ค์„ ๋•Œ Valgrind ์‚ฌ์šฉ๋ฒ•๋„ ํ•จ๊ป˜ ๋ฐฐ์šฐ๋ฉด ๊ฐœ๋ฐœ ์‹ค๋ ฅ์ด ํ™• ์˜ฌ๋ผ๊ฐˆ ์ˆ˜ ์žˆ์–ด์š”! ๐Ÿ‘

5. Valgrind ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ์‚ดํŽด๋ณด๊ธฐ ๐Ÿ”

๊ธฐ๋ณธ์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ๊ฒ€์ถœ ์™ธ์—๋„ Valgrind๋Š” ๋‹ค์–‘ํ•œ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์š”. ์ด์ œ ์ข€ ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€๋ณผ๊นŒ์š”? ๐Ÿ˜Ž

Cachegrind: ์บ์‹œ ํ”„๋กœํŒŒ์ผ๋ง ๐Ÿ“Š

ํ”„๋กœ๊ทธ๋žจ์˜ ์บ์‹œ ์‚ฌ์šฉ๋Ÿ‰์„ ๋ถ„์„ํ•ด์„œ ์„ฑ๋Šฅ ๋ณ‘๋ชฉ ํ˜„์ƒ์„ ์ฐพ์•„๋‚ด๋Š” ๋„๊ตฌ์˜ˆ์š”.

valgrind --tool=cachegrind ./my_program

์ด ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์บ์‹œ ๋ฏธ์Šค, ์ฐธ์กฐ ๋“ฑ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์–ด์š”. ๊ฒฐ๊ณผ๋Š” cachegrind.out.xxxx ํŒŒ์ผ๋กœ ์ €์žฅ๋˜๋Š”๋ฐ, ์ด๊ฑธ cg_annotate ๋„๊ตฌ๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์–ด์š”:

cg_annotate cachegrind.out.xxxx

์ด ๊ธฐ๋Šฅ์€ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ๋•Œ ์–ด๋–ค ํ•จ์ˆ˜๊ฐ€ ์บ์‹œ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์–ด์„œ ์ •๋ง ์œ ์šฉํ•ด์š”!

Callgrind: ํ•จ์ˆ˜ ํ˜ธ์ถœ ํ”„๋กœํŒŒ์ผ๋ง ๐Ÿ“ž

ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ทธ๋ž˜ํ”„์™€ ๊ฐ ํ•จ์ˆ˜์˜ ์‹คํ–‰ ๋น„์šฉ์„ ๋ถ„์„ํ•ด์ฃผ๋Š” ๋„๊ตฌ์˜ˆ์š”.

valgrind --tool=callgrind ./my_program

๊ฒฐ๊ณผ๋Š” callgrind.out.xxxx ํŒŒ์ผ๋กœ ์ €์žฅ๋˜๋ฉฐ, callgrind_annotate๋‚˜ KCachegrind(GUI ๋„๊ตฌ)๋กœ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”:

callgrind_annotate callgrind.out.xxxx

์ด ๋„๊ตฌ๋Š” ์–ด๋–ค ํ•จ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ๋งŽ์€ ์‹œ๊ฐ„์„ ์†Œ๋น„ํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ๋งค์šฐ ์œ ์šฉํ•ด์š”!

Massif: ํž™ ํ”„๋กœํŒŒ์ผ๋Ÿฌ ๐Ÿ“ˆ

ํ”„๋กœ๊ทธ๋žจ์˜ ํž™ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋ถ„์„ํ•ด์ฃผ๋Š” ๋„๊ตฌ์˜ˆ์š”.

valgrind --tool=massif ./my_program

๊ฒฐ๊ณผ๋Š” massif.out.xxxx ํŒŒ์ผ๋กœ ์ €์žฅ๋˜๋ฉฐ, ms_print ๋„๊ตฌ๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์–ด์š”:

ms_print massif.out.xxxx

์ด ๋„๊ตฌ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์–ธ์ œ, ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์‹œ๊ฐํ™”ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋ผ์š”!

Helgrind: ์Šค๋ ˆ๋“œ ์˜ค๋ฅ˜ ๊ฒ€์ถœ๊ธฐ ๐Ÿงต

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฐ์ดํ„ฐ ๋ ˆ์ด์Šค์™€ ๋ฝ ๋ฌธ์ œ๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๋„๊ตฌ์˜ˆ์š”.

valgrind --tool=helgrind ./my_threaded_program

์ด ๋„๊ตฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋“ค์„ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ์–ด์š”:

  1. ๋ฐ์ดํ„ฐ ๋ ˆ์ด์Šค (์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผ)
  2. ๋ฝ ์ˆœ์„œ ์œ„๋ฐ˜ (๋ฐ๋“œ๋ฝ ๊ฐ€๋Šฅ์„ฑ)
  3. ์ž˜๋ชป๋œ pthread API ์‚ฌ์šฉ

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ •๋ง ์–ด๋ ค์šด๋ฐ, Helgrind๊ฐ€ ์žˆ์œผ๋ฉด ๋ˆˆ์— ๋ณด์ด์ง€ ์•Š๋Š” ๋™์‹œ์„ฑ ๋ฒ„๊ทธ๋ฅผ ์ฐพ๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋ผ์š”!

DRD: ๋˜ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ ์˜ค๋ฅ˜ ๊ฒ€์ถœ๊ธฐ ๐Ÿ”„

Helgrind์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด ์Šค๋ ˆ๋“œ ๋ฌธ์ œ๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๋„๊ตฌ์˜ˆ์š”.

valgrind --tool=drd ./my_threaded_program

DRD๋Š” Helgrind๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋œ ์‚ฌ์šฉํ•˜๊ณ  ํŠน์ • ์œ ํ˜•์˜ ์˜ค๋ฅ˜๋ฅผ ๋” ์ž˜ ์ฐพ์•„๋‚ด๊ธฐ๋„ ํ•ด์š”. ๋‘ ๋„๊ตฌ๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•ด๋ณด๋ฉด ๋” ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์–ด์š”!

์‚ฌ์šฉ์ž ์ •์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฒดํฌ ๐Ÿ› ๏ธ

Valgrind์˜ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ(Client Requests) API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์—์„œ ์ง์ ‘ Valgrind์—๊ฒŒ ํŠน์ • ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์ฒดํฌํ•˜๋„๋ก ์š”์ฒญํ•  ์ˆ˜ ์žˆ์–ด์š”.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:

#include <valgrind/memcheck.h>

void check_memory() {
    int *array = malloc(10 * sizeof(int));
    
    // Valgrind์—๊ฒŒ ์ด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜๋‹ค๊ณ  ํ‘œ์‹œ
    VALGRIND_MAKE_MEM_UNDEFINED(array, 10 * sizeof(int));
    
    // ํŠน์ • ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ
    VALGRIND_CHECK_MEM_IS_ADDRESSABLE(array, 10 * sizeof(int));
    
    // ํŠน์ • ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์ด ์ดˆ๊ธฐํ™”๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
    VALGRIND_CHECK_MEM_IS_DEFINED(array, 10 * sizeof(int));
    
    free(array);
}

์ด๋Ÿฐ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๋“ค์„ ํ™œ์šฉํ•˜๋ฉด ๋‹จ์ˆœํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ๊ฒ€์ถœ์„ ๋„˜์–ด์„œ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ๊ณผ ์•ˆ์ •์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”. ํŠนํžˆ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ด๋Ÿฐ ๋„๊ตฌ๋“ค์ด ์ •๋ง ๋น›์„ ๋ฐœํ•œ๋‹ต๋‹ˆ๋‹ค! โœจ

6. ์‹ค์ „ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” Valgrind ๐Ÿ’ป

์ด๋ก ์€ ์ถฉ๋ถ„ํžˆ ๋ฐฐ์› ์œผ๋‹ˆ ์ด์ œ ์‹ค์ „ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด Valgrind๋ฅผ ์ œ๋Œ€๋กœ ํ™œ์šฉํ•ด๋ณผ๊ฒŒ์š”! ์‹ค์ œ๋กœ ์ž์ฃผ ๋งŒ๋‚˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์ƒํ™ฉ๋“ค์„ ์‚ดํŽด๋ณผ๊ฑฐ์˜ˆ์š”.

์˜ˆ์ œ 1: ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์ฐพ๊ธฐ

๋จผ์ € ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”:

// memory_leak_example.c
#include <stdlib.h>
#include <stdio.h>

void function_with_leak() {
    int *data = malloc(100 * sizeof(int));
    data[0] = 1;  // ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ
    // free(data)๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Œ
}

int main() {
    for(int i = 0; i < 10; i++) {
        function_with_leak();  // 10๋ฒˆ ํ˜ธ์ถœํ•˜๋ฉด 10๋ฒˆ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ
    }
    printf("Program completed\n");
    return 0;
}

์ด ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๊ณ  Valgrind๋กœ ์‹คํ–‰ํ•ด๋ณผ๊ฒŒ์š”:

gcc -g memory_leak_example.c -o memory_leak_example
valgrind --leak-check=full ./memory_leak_example

๊ฒฐ๊ณผ:

==12345== HEAP SUMMARY:
==12345==     in use at exit: 4,000 bytes in 10 blocks
==12345==   total heap usage: 10 allocs, 0 frees, 4,000 bytes allocated
==12345== 
==12345== 4,000 bytes in 10 blocks are definitely lost in loss record 1 of 1
==12345==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12345==    by 0x109177: function_with_leak (memory_leak_example.c:5)
==12345==    by 0x109199: main (memory_leak_example.c:11)

Valgrind๊ฐ€ ์ •ํ™•ํžˆ 10๊ฐœ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก์ด ๋ˆ„์ˆ˜๋˜์—ˆ๋‹ค๊ณ  ์•Œ๋ ค์ฃผ๋„ค์š”! ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ค ํ•จ์ˆ˜์—์„œ ๋ฐœ์ƒํ–ˆ๋Š”์ง€๋„ ์ •ํ™•ํžˆ ์•Œ๋ ค์ค˜์š”.

ํ•ด๊ฒฐ์ฑ…:

void function_with_leak() {
    int *data = malloc(100 * sizeof(int));
    data[0] = 1;
    free(data);  // ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ์ถ”๊ฐ€
}

์˜ˆ์ œ 2: ๋ฐฐ์—ด ๋ฒ”์œ„ ์ดˆ๊ณผ ์ ‘๊ทผ

๋ฐฐ์—ด ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” ์ ‘๊ทผ์„ ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”:

// buffer_overflow.c
#include <stdio.h>

int main() {
    int array[5] = {1, 2, 3, 4, 5};
    
    // ๋ฐฐ์—ด ๋ฒ”์œ„ ๋‚ด ์ ‘๊ทผ (์ •์ƒ)
    printf("array[4] = %d\n", array[4]);
    
    // ๋ฐฐ์—ด ๋ฒ”์œ„ ์ดˆ๊ณผ ์ ‘๊ทผ (์˜ค๋ฅ˜)
    printf("array[10] = %d\n", array[10]);
    
    return 0;
}

์ปดํŒŒ์ผํ•˜๊ณ  Valgrind๋กœ ์‹คํ–‰:

gcc -g buffer_overflow.c -o buffer_overflow
valgrind ./buffer_overflow

๊ฒฐ๊ณผ:

==12345== Invalid read of size 4
==12345==    at 0x109177: main (buffer_overflow.c:10)
==12345==  Address 0xffefffb28 is 24 bytes after a block of size 20 in stack

Valgrind๊ฐ€ ๋ฐฐ์—ด ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ์ฝ๊ธฐ ์ ‘๊ทผ์„ ์ •ํ™•ํžˆ ์ฐพ์•„๋ƒˆ์–ด์š”! ์ด๋Ÿฐ ์˜ค๋ฅ˜๋Š” C์—์„œ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์žก์•„๋‚ด์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์„œ ๋Ÿฐํƒ€์ž„์— ์ด์ƒํ•œ ๊ฐ’์ด ์ถœ๋ ฅ๋˜๊ฑฐ๋‚˜ ๋” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”.

์˜ˆ์ œ 3: ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๋ณ€์ˆ˜ ์‚ฌ์šฉ

์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š์€ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”:

// uninitialized.c
#include <stdio.h>

int main() {
    int x;  // ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š์Œ
    int y = 10;
    
    if(x > 0) {  // ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ x ์‚ฌ์šฉ
        printf("x is positive: %d\n", x);
    } else {
        printf("x is not positive: %d\n", x);
    }
    
    int result = x + y;  // ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๊ฐ’์œผ๋กœ ๊ณ„์‚ฐ
    printf("Result: %d\n", result);
    
    return 0;
}

์ปดํŒŒ์ผํ•˜๊ณ  Valgrind๋กœ ์‹คํ–‰:

gcc -g uninitialized.c -o uninitialized
valgrind --track-origins=yes ./uninitialized

๊ฒฐ๊ณผ:

==12345== Conditional jump or move depends on uninitialised value(s)
==12345==    at 0x109177: main (uninitialized.c:7)
==12345==  Uninitialised value was created by a stack allocation
==12345==    at 0x109166: main (uninitialized.c:4)
==12345== 
==12345== Use of uninitialised value of size 4
==12345==    at 0x109199: main (uninitialized.c:14)

Valgrind๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๊ฐ’์˜ ์‚ฌ์šฉ์„ ์ •ํ™•ํžˆ ์ฐพ์•„๋ƒˆ์–ด์š”! --track-origins=yes ์˜ต์…˜ ๋•๋ถ„์— ์–ด๋””์„œ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๊ฐ’์ด ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€๋„ ์•Œ ์ˆ˜ ์žˆ์–ด์š”.

ํ•ด๊ฒฐ์ฑ…:

int main() {
    int x = 0;  // ์ดˆ๊ธฐํ™” ์ถ”๊ฐ€
    int y = 10;
    
    // ์ด์ œ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    if(x > 0) {
        printf("x is positive: %d\n", x);
    } else {
        printf("x is not positive: %d\n", x);
    }
    
    int result = x + y;
    printf("Result: %d\n", result);
    
    return 0;
}

์˜ˆ์ œ 4: ํ•ด์ œ ํ›„ ์‚ฌ์šฉ (Use After Free)

๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•œ ํ›„์— ์ ‘๊ทผํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”:

// use_after_free.c
#include <stdlib.h>
#include <stdio.h>

int main() {
    int *ptr = (int*)malloc(sizeof(int));
    *ptr = 10;
    
    printf("Before free: *ptr = %d\n", *ptr);
    
    free(ptr);  // ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ
    
    // ํ•ด์ œ ํ›„ ์ ‘๊ทผ (์˜ค๋ฅ˜)
    *ptr = 20;  // ์“ฐ๊ธฐ ์ ‘๊ทผ
    printf("After free: *ptr = %d\n", *ptr);  // ์ฝ๊ธฐ ์ ‘๊ทผ
    
    return 0;
}

์ปดํŒŒ์ผํ•˜๊ณ  Valgrind๋กœ ์‹คํ–‰:

gcc -g use_after_free.c -o use_after_free
valgrind ./use_after_free

๊ฒฐ๊ณผ:

==12345== Invalid write of size 4
==12345==    at 0x109177: main (use_after_free.c:12)
==12345==  Address 0x4a37040 is 0 bytes inside a block of size 4 free'd
==12345==    at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12345==    by 0x109166: main (use_after_free.c:9)
==12345== 
==12345== Invalid read of size 4
==12345==    at 0x109199: main (use_after_free.c:13)

Valgrind๊ฐ€ ํ•ด์ œ๋œ ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ ์ ‘๊ทผ ๋ชจ๋‘ ์ฐพ์•„๋ƒˆ์–ด์š”! ์ด๋Ÿฐ ์˜ค๋ฅ˜๋Š” ์ •๋ง ์œ„ํ—˜ํ•œ๋ฐ, ๋•Œ๋กœ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์ถฉ๋Œํ•˜์ง€ ์•Š๊ณ  ๊ณ„์† ์‹คํ–‰๋˜๋ฉด์„œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

ํ•ด๊ฒฐ์ฑ…:

int main() {
    int *ptr = (int*)malloc(sizeof(int));
    *ptr = 10;
    
    printf("Before free: *ptr = %d\n", *ptr);
    
    free(ptr);
    ptr = NULL;  // ํ•ด์ œ ํ›„ NULL๋กœ ์„ค์ •
    
    // NULL ์ฒดํฌ ์ถ”๊ฐ€
    if (ptr != NULL) {
        *ptr = 20;
        printf("After free: *ptr = %d\n", *ptr);
    }
    
    return 0;
}

์ด๋Ÿฐ ์‹ค์ „ ์˜ˆ์ œ๋“ค์„ ํ†ตํ•ด Valgrind๊ฐ€ ์–ผ๋งˆ๋‚˜ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ธ์ง€ ๋А๊ปด์ง€์‹œ๋‚˜์š”? ๐Ÿ˜ฒ C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ จ ๋ฒ„๊ทธ๋Š” ์ฐพ๊ธฐ ์ •๋ง ์–ด๋ ค์šด๋ฐ, Valgrind๋Š” ์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ์ •ํ™•ํžˆ ์งš์–ด๋‚ด์ค˜์š”!

์žฌ๋Šฅ๋„ท์—์„œ C ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ•์˜๋ฅผ ๋“ค์œผ์‹œ๋Š” ๋ถ„๋“ค์ด๋ผ๋ฉด, ๊ผญ Valgrind ์‚ฌ์šฉ๋ฒ•๋„ ํ•จ๊ป˜ ์ตํ˜€๋ณด์„ธ์š”. ์ฝ”๋”ฉ ์‹ค๋ ฅ์ด ํ•œ ๋‹จ๊ณ„ ์—…๊ทธ๋ ˆ์ด๋“œ๋  ๊ฑฐ์˜ˆ์š”! ๐Ÿ’ฏ

7. ์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ๋“ค โ“

Valgrind๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋งŽ์€ ๋ถ„๋“ค์ด ๊ถ๊ธˆํ•ดํ•˜์‹œ๋Š” ์งˆ๋ฌธ๋“ค์„ ๋ชจ์•„๋ดค์–ด์š”!

Q: Valgrind๊ฐ€ ๋„ˆ๋ฌด ๋А๋ ค์š”. ๋” ๋น ๋ฅด๊ฒŒ ์‚ฌ์šฉํ•  ๋ฐฉ๋ฒ•์ด ์žˆ๋‚˜์š”? ๐Ÿข

A: ๋„ค, Valgrind๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœ๊ทธ๋žจ์„ 10~30๋ฐฐ ๋А๋ฆฌ๊ฒŒ ์‹คํ–‰ํ•ด์š”. ์†๋„๋ฅผ ์กฐ๊ธˆ ๊ฐœ์„ ํ•˜๋ ค๋ฉด:

  1. ์ตœ์ ํ™” ์˜ต์…˜ ์—†์ด ์ปดํŒŒ์ผ(-O0)ํ•˜๋ฉด Valgrind๊ฐ€ ๋” ์ •ํ™•ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•ด์š”.
  2. --undef-value-errors=no ์˜ต์…˜์œผ๋กœ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๊ฐ’ ๊ฒ€์‚ฌ๋ฅผ ๋Œ ์ˆ˜ ์žˆ์–ด์š”(๊ถŒ์žฅํ•˜์ง„ ์•Š์•„์š”).
  3. ํ”„๋กœ๊ทธ๋žจ์˜ ์ผ๋ถ€๋ถ„๋งŒ ๋ถ„์„ํ•˜๋ ค๋ฉด VALGRIND_DISABLE_ERROR_REPORTING์™€ VALGRIND_ENABLE_ERROR_REPORTING ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

ํ•˜์ง€๋งŒ ์ •ํ™•ํ•œ ๋ถ„์„์„ ์œ„ํ•ด์„œ๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜๋‹ˆ ์ฐธ๊ณ  ๊ธฐ๋‹ค๋ฆผ์ด ํ•„์š”ํ•ด์š”! โณ

Q: Valgrind๊ฐ€ "still reachable" ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ณด๊ณ ํ•ด์š”. ์ด๊ฒŒ ๋ฌธ์ œ์ธ๊ฐ€์š”? ๐Ÿค”

A: "still reachable"์€ ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋  ๋•Œ ์•„์ง ํฌ์ธํ„ฐ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์˜๋ฏธํ•ด์š”. ์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ๋ˆ„์ˆ˜๋Š” ์•„๋‹ˆ์—์š”. ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋˜๋ฉด OS๊ฐ€ ์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšŒ์ˆ˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .

ํ•˜์ง€๋งŒ ์ข‹์€ ์Šต๊ด€์„ ์œ„ํ•ด ๊ฐ€๋Šฅํ•˜๋ฉด ๋ชจ๋“  ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ•ด์ œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”! ํŠนํžˆ ์˜ค๋ž˜ ์‹คํ–‰๋˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” ์ค‘์š”ํ•ด์š”.

Q: ์‹œ์Šคํ…œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋‚˜์š”? ๐Ÿ“š

A: ์‹œ์Šคํ…œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜๋Š” ๋ณดํ†ต ๋ฌด์‹œํ•ด๋„ ๋ผ์š”. Valgrind๋Š” --suppressions ์˜ต์…˜์œผ๋กœ ์ด๋Ÿฐ ์˜ค๋ฅ˜๋ฅผ ์ˆจ๊ธธ ์ˆ˜ ์žˆ์–ด์š”:

valgrind --suppressions=/path/to/suppression.supp ./my_program

๊ธฐ๋ณธ ์ œ๊ณต๋˜๋Š” ์–ต์ œ ํŒŒ์ผ๋„ ์žˆ๊ณ , ์ง์ ‘ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์–ด์š”:

valgrind --gen-suppressions=all ./my_program

Q: Valgrind๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๋ณด๊ณ ํ•˜์ง€๋งŒ ๋‚ด ์ฝ”๋“œ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์–ด ๋ณด์—ฌ์š”. ์™œ ๊ทธ๋Ÿด๊นŒ์š”? ๐Ÿงฉ

A: ๋ช‡ ๊ฐ€์ง€ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด์š”:

  1. ์ตœ์ ํ™” ์ปดํŒŒ์ผ(-O2, -O3)๋กœ ์ธํ•ด ์ฝ”๋“œ๊ฐ€ ๋ณ€ํ˜•๋˜์—ˆ์„ ์ˆ˜ ์žˆ์–ด์š”. ๋””๋ฒ„๊น…ํ•  ๋•Œ๋Š” -O0 ์˜ต์…˜์„ ์‚ฌ์šฉํ•ด๋ณด์„ธ์š”.
  2. ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ์ˆ˜ ์žˆ์–ด์š”.
  3. ์กฐ๊ฑด๋ถ€ ์˜ค๋ฅ˜์ผ ์ˆ˜ ์žˆ์–ด์š”. ํŠน์ • ์ž…๋ ฅ์ด๋‚˜ ์ƒํ™ฉ์—์„œ๋งŒ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜์ฃ .

Valgrind๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ ์‹ค์ œ ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ ํ•ด์š”. ์˜คํƒ(false positive)์ด ์žˆ๊ธด ํ•˜์ง€๋งŒ ๋“œ๋ฌผ์–ด์š”!

Q: Windows์—์„œ Valgrind ๋Œ€์‹  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๊ฐ€ ์žˆ๋‚˜์š”? ๐ŸชŸ

A: ๋„ค, Windows์—์„œ๋Š” ๋‹ค์Œ ๋„๊ตฌ๋“ค์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ์–ด์š”:

  1. Dr. Memory: Valgrind์™€ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ Windows์—์„œ ๋„ค์ดํ‹ฐ๋ธŒ๋กœ ๋™์ž‘ํ•ด์š”.
  2. Visual Studio์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ฒ€์‚ฌ ๋„๊ตฌ: Visual Studio์— ๋‚ด์žฅ๋œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐ ์˜ค๋ฅ˜ ๊ฒ€์ถœ ๋„๊ตฌ๊ฐ€ ์žˆ์–ด์š”.
  3. Intel Inspector: ์ƒ์šฉ ๋„๊ตฌ์ง€๋งŒ ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ ์Šค๋ ˆ๋“œ ์˜ค๋ฅ˜ ๊ฒ€์ถœ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์š”.

ํ•˜์ง€๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด WSL(Windows Subsystem for Linux)์—์„œ Valgrind๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์—์š”!

Q: Valgrind ๊ฒฐ๊ณผ๋ฅผ ๋” ๋ณด๊ธฐ ์ข‹๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‚˜์š”? ๐ŸŽจ

A: ๋„ค, ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์š”:

  1. valkyrie: Valgrind์˜ GUI ํ”„๋ก ํŠธ์—”๋“œ๋กœ, ๊ฒฐ๊ณผ๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ๋ณด์—ฌ์ค˜์š”.
  2. KCachegrind: Callgrind ๊ฒฐ๊ณผ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๋Š” ๋„๊ตฌ์˜ˆ์š”.
  3. --log-file ์˜ต์…˜์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ํŒŒ์ผ๋กœ ์ €์žฅํ•œ ํ›„ ํ…์ŠคํŠธ ์—๋””ํ„ฐ๋กœ ๋ณด๋ฉด ์ƒ‰์ƒ ๊ตฌ๋ถ„์ด ๋” ์ž˜ ๋ณด์ผ ์ˆ˜ ์žˆ์–ด์š”.

IDE ํ†ตํ•ฉ๋„ ์žˆ์–ด์š”. Eclipse CDT, CLion, Visual Studio Code ๋“ฑ์—์„œ Valgrind ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”!

์ด๋Ÿฐ ์งˆ๋ฌธ๋“ค์ด Valgrind๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ์˜๋ฌธ์ ๋“ค์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ผ์š”! ๋” ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ์œผ์‹œ๋ฉด ์žฌ๋Šฅ๋„ท ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์งˆ๋ฌธํ•ด๋ณด์„ธ์š”. ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๊ธฐ๊บผ์ด ๋„์›€์„ ์ค„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜Š

๋งˆ์น˜๋ฉฐ ๐ŸŽฏ

์ง€๊ธˆ๊นŒ์ง€ Valgrind๋ฅผ ์‚ฌ์šฉํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ๊ฒ€์ถœ์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์–ด์š”! ์–ด๋•Œ์š”? ์ƒ๊ฐ๋ณด๋‹ค ์‰ฝ์ฃ ? ใ…‹ใ…‹ใ…‹

C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋Š” ์ •๋ง ๊นŒ๋‹ค๋กœ์šด ๋ถ€๋ถ„์ด์ง€๋งŒ, Valgrind ๊ฐ™์€ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ์žˆ์œผ๋ฉด ํ›จ์”ฌ ์ˆ˜์›”ํ•˜๊ฒŒ ๋””๋ฒ„๊น…ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜, ์ž˜๋ชป๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ, ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ๋“ฑ C ํ”„๋กœ๊ทธ๋ž˜๋จธ๋“ค์ด ์ž์ฃผ ๊ฒช๋Š” ๋ฌธ์ œ๋“ค์„ ์‰ฝ๊ฒŒ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ์ฃ !

ํŠนํžˆ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Valgrind ๊ฐ™์€ ๋„๊ตฌ ์—†์ด ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜๋ฅผ ์ฐพ์•„๋‚ด๊ธฐ๊ฐ€ ๊ฑฐ์˜ ๋ถˆ๊ฐ€๋Šฅ์— ๊ฐ€๊นŒ์›Œ์š”. ๊ทธ๋ž˜์„œ ์ „๋ฌธ ๊ฐœ๋ฐœ์ž๋“ค์€ ํ•ญ์ƒ ์ด๋Ÿฐ ๋„๊ตฌ๋“ค์„ ์ ๊ทน ํ™œ์šฉํ•œ๋‹ต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ถ„๋„ ์ด์ œ Valgrind๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋” ์•ˆ์ •์ ์ด๊ณ  ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์—†๋Š” C ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”! ์ฒ˜์Œ์—๋Š” ์ข€ ์–ด์ƒ‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ต์ˆ™ํ•ด์ง€๋ฉด ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ์—†์–ด์„œ๋Š” ์•ˆ ๋  ํ•„์ˆ˜ ๋„๊ตฌ๊ฐ€ ๋  ๊ฑฐ์˜ˆ์š”! ๐Ÿ’ฏ

ํ˜น์‹œ C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ๋””๋ฒ„๊น…์— ๋Œ€ํ•ด ๋” ๋ฐฐ์šฐ๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด, ์žฌ๋Šฅ๋„ท์—์„œ ๊ด€๋ จ ๊ฐ•์˜๋ฅผ ์ฐพ์•„๋ณด์„ธ์š”. ๋‹ค์–‘ํ•œ ์ „๋ฌธ๊ฐ€๋“ค์ด ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์‹ค๋ ฅ ํ–ฅ์ƒ์„ ๋„์™€์ค„ ๊ฑฐ์˜ˆ์š”! ๐Ÿš€

๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜ ์—†๋Š” ํ–‰๋ณตํ•œ ์ฝ”๋”ฉ ๋˜์„ธ์š”! ๐Ÿ‘‹

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.