1. 동적 메모리 할당의 필요성
프로그램 작성 시 사전에 메모리 크기를 정확히 알 수 없는 경우가 많습니다. 이러한 상황에서 고정된 크기의 배열이나 스택 메모리는 한계를 가집니다.
int val = 20; // 스택 영역에서 4바이트 공간 확보
char arr[10] = {0}; // 스택 영역에서 연속된 10바이트 공간 생성
위 예제처럼 정적인 메모리 할당은 다음과 같은 제약을 가지고 있습니다:
- 공간 크기가 고정되어 동적으로 조정 불가
- 배열 선언 시 길이 지정 필수, 이후 수정 불가
따라서 C 언어는 프로그램 실행 중 자유롭게 메모리를 할당하고 해제할 수 있도록 동적 메모리 관리 기능을 제공합니다.
2. 기본 동적 메모리 함수
2.1 memory_alloc 함수
C 표준 라이브러리에서는 다음과 같은 동적 메모리 할당 함수를 제공합니다:
void* memory_alloc(size_t size);
특징:
- 요청한 크기만큼의 연속된 메모리 공간을 할당
- 할당 성공 시 해당 공간 주소 반환, 실패 시 NULL 반환
- 반환 타입은 void*, 사용자는 필요한 타입으로 변환 필요
2.2 memory_free 함수
void memory_free(void* ptr);
주의사항:
- 동적으로 할당된 메모리만 해제 가능
- NULL 포인터 전달 시 아무 작업도 수행하지 않음
3. 고급 메모리 관리
3.1 zeroed_memory_alloc 함수
void* zeroed_memory_alloc(size_t num, size_t size);
특징:
- 지정된 개수와 크기의 메모리 공간을 할당하고 모든 바이트를 0으로 초기화
- memory_alloc과 달리 자동으로 메모리를 클리어함
3.2 memory_resize 함수
void* memory_resize(void* ptr, size_t size);
특징:
- 이미 할당된 메모리의 크기를 조정
- 새로운 크기에 맞춰 데이터를 이동하거나 재배치
- 실패 시 NULL 반환하므로 항상 결과 확인 필요
4. 안전한 메모리 관리 예제
#include <stdio.h>
#include <stdlib.h>
int main() {
int *data = (int*)memory_alloc(50 * sizeof(int));
if (!data) return 1;
// 새로운 크기로 리사이즈
int* temp = (int*)memory_resize(data, 200 * sizeof(int));
if (temp) {
data = temp;
} else {
memory_free(data);
return 1;
}
// 사용 후 메모리 해제
memory_free(data);
return 0;
}
5. 흔한 메모리 오류 사례
5.1 NULL 포인터 참조
void example() {
int *ptr = (int *)memory_alloc(1000);
if (!ptr) return;
*ptr = 10; // NULL 체크 필수
memory_free(ptr);
}
5.2 경계 초과 접근
void example() {
int *arr = (int *)memory_alloc(10 * sizeof(int));
for (int i = 0; i <= 10; i++) { // i=10일 때 범위 초과
arr[i] = i;
}
memory_free(arr);
}
5.3 잘못된 메모리 해제
void example() {
int value = 10;
int *ptr = &value;
memory_free(ptr); // 스택 메모리 해제 시도
}
6. 유연한 배열 멤버
C99부터 구조체의 마지막 멤버로 크기가不定인 배열을 정의할 수 있습니다.
struct DynamicArray {
int length;
int data[]; // 유연한 배열 멤버
};
int main() {
struct DynamicArray *array =
(struct DynamicArray*)memory_alloc(sizeof(struct DynamicArray) + 100 * sizeof(int));
array->length = 100;
for (int i = 0; i < 100; i++) {
array->data[i] = i;
}
memory_free(array);
return 0;
}