null
vuild_
Nodes
Flows
Hubs
Login
MENU
Notifications
Login
⌂
c-lang-intermediate
Structure
pointers
•
포인터 기초 (Pointer Basics)
•
배열과 포인터 (Pointer & Array)
•
포인터와 함수 (Pointer & Function)
memory
•
스택과 힙 (Stack & Heap)
•
메모리 레이아웃 (Memory Layout)
dynamic-alloc
•
malloc과 free (malloc & free)
•
calloc과 realloc
•
메모리 누수 (Memory Leak)
struct
•
구조체 기초 (Struct Basics)
•
중첩 구조체, 구조체 배열, 구조체 포인터
•
union과 enum
file-io
•
파일 열기와 닫기 (fopen / fclose)
•
파일 읽기와 쓰기 (Read & Write)
•
바이너리 파일 (Binary File)
preprocessor
•
#define과 매크로 (Define & Macro)
•
헤더 중복 포함 방지 (Include Guard)
•
조건부 컴파일 (Conditional Compilation)
multi-file
•
헤더 파일 (Header Files)
•
extern과 static (Extern & Static)
•
Makefile 기초 (Makefile Basics)
debugging
•
GDB 기초 (GDB Basics)
•
Valgrind
•
자주 발생하는 C 오류 (Common Errors)
project
•
종합 프로젝트: 학생 관리 시스템 (Student Manager)
Flow Structure
calloc과 realloc
8 / 24
구조체 기초 (Struct Basics)
☆ Star
↗ Full
메모리 누수 (Memory Leak)
#c
#c-lang
#intermediate
#memory-leak
#dynamic-allocation
@devpc
|
2026-03-29 13:06:58
|
GET /api/v1/flows/5/nodes/48?fv=2&nv=2
Context:
Flow v2
→
Node v2
0
Views
6
Calls
# 메모리 누수 (Memory Leak) ## 메모리 누수란? 동적으로 할당한 메모리를 `free`하지 않아 **프로세스가 끝날 때까지 해당 메모리가 반환되지 않는 현상**입니다. ```c void leak_example(void) { int *p = malloc(sizeof(int) * 100); // ... 사용 ... // free(p) 없이 함수 종료 → 100*4 = 400바이트 누수 } ``` 반복 호출 시 메모리가 점점 부족해지고 결국 프로그램이 비정상 종료됩니다. --- ## 주요 누수 원인 ### 1. free 누락 ```c char *buf = malloc(256); // ... 사용 후 free 없음 ``` ### 2. 포인터 덮어쓰기 ```c int *p = malloc(sizeof(int) * 10); p = malloc(sizeof(int) * 20); // ❌ 첫 번째 할당 주소를 잃음 → 누수 ``` ### 3. 조기 반환 시 해제 누락 ```c int *arr = malloc(sizeof(int) * n); if (some_error) { return -1; // ❌ arr을 해제하지 않고 반환 } // ... 처리 ... free(arr); return 0; ``` ### 4. 연결 리스트 부분 해제 ```c struct Node { int data; struct Node *next; }; // ❌ 전체를 순회하며 해제하지 않고 head만 해제 free(head); ``` --- ## 안전한 해제 패턴 ### 조기 반환 패턴 — goto cleanup ```c int process(int n) { int *a = NULL, *b = NULL; a = malloc(sizeof(int) * n); if (!a) goto cleanup; b = malloc(sizeof(int) * n); if (!b) goto cleanup; // ... 처리 ... cleanup: free(a); free(b); // NULL 해제는 안전 return 0; } ``` ### 연결 리스트 전체 해제 ```c void free_list(struct Node *head) { while (head) { struct Node *next = head->next; free(head); head = next; } } ``` ### 해제 후 NULL 초기화 ```c free(p); p = NULL; // 댕글링 포인터 방지 + 이중 해제 방지 ``` --- ## 탐지 방법 ### 1. Valgrind (Linux/macOS) ```bash gcc -g -o program program.c valgrind --leak-check=full ./program ``` **출력 예시:** ``` ==1234== LEAK SUMMARY: ==1234== definitely lost: 400 bytes in 1 blocks ==1234== indirectly lost: 0 bytes in 0 blocks ==1234== possibly lost: 0 bytes in 0 blocks ==1234== still reachable: 0 bytes in 0 blocks ``` ### 2. Address Sanitizer (ASan) ```bash gcc -fsanitize=address -g -o program program.c ./program ``` 메모리 오류 및 누수를 런타임에 탐지합니다. ### 3. 정적 분석 — clang-tidy / cppcheck ```bash cppcheck --enable=all program.c ``` 코드를 실행하지 않고 분석합니다. --- ## 누수 방지 체크리스트 ``` ✅ 모든 malloc/calloc에 대응하는 free가 있는가? ✅ 포인터를 덮어쓰기 전에 기존 메모리를 해제했는가? ✅ 조기 반환(return/goto) 경로에서도 해제했는가? ✅ 재할당(realloc) 실패 시 원본 포인터를 해제했는가? ✅ 연결 리스트 등 복합 구조체를 모두 순회하며 해제했는가? ✅ free 후 포인터를 NULL로 초기화했는가? ``` --- ## 전체 예제 — 누수 없는 동적 배열 ```c #include <stdio.h> #include <stdlib.h> int *create_array(int n) { int *arr = malloc(sizeof(int) * n); if (!arr) return NULL; for (int i = 0; i < n; i++) { arr[i] = i; } return arr; // 호출한 쪽에서 반드시 free } int main(void) { int *data = create_array(10); if (!data) { fprintf(stderr, "allocation failed\n"); return 1; } for (int i = 0; i < 10; i++) { printf("%d ", data[i]); } printf("\n"); free(data); // 반드시 해제 data = NULL; return 0; } ``` --- ## 정리 | 원인 | 해결 | |------|------| | free 누락 | 모든 동적 할당에 대응하는 free 추가 | | 포인터 덮어쓰기 | 재할당 전 기존 메모리 해제 | | 조기 반환 | goto cleanup 패턴 사용 | | 복합 구조체 | 재귀/반복으로 전체 해제 | | 탐지 | Valgrind, ASan, 정적 분석 도구 활용 | ---
calloc과 realloc
구조체 기초 (Struct Basics)
// COMMENTS
ON THIS PAGE
No content selected.