0Pricing
C Academy · 강의

누수 감지

memcheck 기초를 알아봅니다

누수 감지은(는) CoddyKit의 무료 C Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

누수란 무엇인가

메모리 누수는 malloc, calloc 또는 realloc으로 힙 메모리를 할당한 뒤 free를 호출하기 전에 해당 메모리를 가리키는 모든 포인터를 잃어버릴 때 발생합니다.

이 블록은 프로세스가 종료될 때까지 예약된 상태로 남지만 접근할 수 없게 됩니다. 장시간 실행되는 프로그램에서는 누수가 계속 쌓여 메모리가 모두 소진됩니다.

최소한의 누수

이 프로그램은 40바이트 크기의 블록 하나를 누수시킵니다.

포인터 p는 지역 변수입니다. main이 반환하면 p는 사라지지만, 포인터가 가리키던 힙 블록은 해제되지 않습니다.

#include <stdlib.h>

int main(void) {
    int *p = malloc(10 * sizeof(int));
    p[0] = 1;
    return 0; /* never free(p) */
}

memcheck 실행하기

memcheck는 기본 도구이므로 도구 이름을 생략할 수 있습니다.

--leak-check=full을 추가하면 누수된 할당마다 호출 스택을 확인할 수 있습니다.

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

누수 요약

Valgrind는 종료할 때 LEAK SUMMARY를 출력합니다. 위 프로그램의 경우 대략 다음과 같이 표시됩니다.

definitely lost: 40 bytes in 1 blocks

추적 결과는 정확한 malloc 호출 위치를 가리키므로 어떤 할당이 해제되지 않았는지 정확히 알 수 있습니다.

누수의 네 가지 범주

memcheck는 유실된 메모리를 네 가지 범주로 분류합니다.

  • definitely lost — 남아 있는 포인터가 없는 진짜 누수
  • indirectly lost — definitely-lost 블록을 통해서만 접근할 수 있는 메모리
  • possibly lost — 내부를 가리키는 포인터만 남은 메모리
  • still reachable — 종료 시 포인터가 존재하지만 해제하지 않은 메모리

Definitely lost와 Still reachable 비교

definitely lost는 가장 긴급한 범주입니다. 프로그램이 실행되는 동안 해당 바이트를 복구할 수 없습니다.

still reachable은 정도가 덜 심각합니다. 종료 시 블록이 누수되지만 전역 또는 정적 포인터가 여전히 이를 참조하므로, 대개 한 번만 할당하고 해제하지 않은 경우입니다.

간접 누수

연결된 구조의 시작 노드를 잃어버리면 모든 노드에 접근할 수 없게 됩니다.

시작 노드는 definitely lost로 표시되고 나머지는 indirectly lost로 표시됩니다. 근본 원인인 유실된 시작 노드를 수정하면 전체를 되찾을 수 있습니다.

struct Node { int v; struct Node *next; };

struct Node *make(void) {
    struct Node *h = malloc(sizeof *h);
    h->next = malloc(sizeof *h);
    h->next->next = NULL;
    return h;
}
/* if the caller drops the returned head, both nodes leak */

수정된 버전

할당한 메모리는 해제하시기 바랍니다. 이 버전에서는 아무것도 누수되지 않습니다.

Valgrind로 실행하면 All heap blocks were freed -- no leaks are possible라고 보고됩니다.

#include <stdlib.h>

int main(void) {
    int *p = malloc(10 * sizeof(int));
    p[0] = 1;
    free(p);
    return 0;
}

할당 횟수 세기

누수가 없더라도 HEAP SUMMARY를 통해 프로그램이 얼마나 많은 작업을 수행했는지 알 수 있습니다.

total heap usage: 1 allocs, 1 frees, 40 bytes allocated

할당 횟수와 해제 횟수가 일치하면 정상적으로 종료된 것입니다. 불일치는 무언가가 빠져나갔다는 첫 번째 단서입니다.

접근 가능한 블록 표시하기

기본적으로 memcheck는 still reachable 블록의 상세 내역을 표시하지 않습니다. 이 블록까지 검사하려면 다음 옵션을 추가합니다.

--show-leak-kinds=all

이 옵션은 모든 범주에 대한 추적 결과를 표시하므로, 종료 전에 모든 메모리를 완전히 해제하는 프로그램을 만들고 싶을 때 유용합니다.

valgrind --leak-check=full --show-leak-kinds=all ./leak

오류 경로에서 발생하는 누수

가장 찾기 어려운 누수는 조기 반환 경로에 숨어 있습니다. 여기서는 두 번째 할당이 실패하면 첫 번째 블록이 누수됩니다.

일반적인 테스트에서는 이런 분기를 거의 실행하지 않지만, 해당 경로가 실행되면 memcheck가 누수를 찾아냅니다. 오류 발생 시 반환하기 전에 보유한 메모리를 항상 해제하시기 바랍니다.

char *a = malloc(100);
char *b = malloc(100);
if (!b) {
    /* bug: a is leaked here */
    return -1;
}
/* fix: free(a); before returning */

빠른 확인

가장 긴급하게 처리해야 하는 누수 범주를 선택하시기 바랍니다.

정리

이제 memcheck로 누수를 찾을 수 있습니다.

  • -g로 컴파일한 이진 파일에 valgrind --leak-check=full ./prog를 실행합니다
  • LEAK SUMMARY와 HEAP SUMMARY를 확인합니다
  • definitely lost를 우선 처리한 다음 간접 누수의 근본 원인을 추적합니다
  • --show-leak-kinds=all을 사용해 still-reachable 블록을 검사합니다

다음 주제는 잘못된 메모리 접근입니다.

자주 묻는 질문

“누수 감지” 강의는 무료인가요?

네 — “누수 감지” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C Academy 강의 전체를 잠금 해제할 수 있습니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“누수 감지”에서 뭘 배우나요?

memcheck 기초를 알아봅니다 브라우저에서 직접 실행하는 실습 코드로 C Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“누수 감지” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Valgrind가 필요한 이유
  2. 누수 감지
  3. 잘못된 접근
  4. 보고서 읽기
← C Academy(으)로 돌아가기