고급 C 프로그래밍 – 동적 메모리 할당과 관리 – 2 – 동적 할당된 메모리 사용하기

고급 C 프로그래밍 – 동적 메모리 할당과 관리 – 2편: 동적 할당된 메모리 사용하기

안녕하세요, 프로그래머 여러분! 😊
이번 시간에는 동적 메모리 할당으로 확보한 메모리를 실제로 어떻게 사용해야 하는지
자세히 알아보는 시간을 가져볼게요!

📦 메모리를 malloc이나 calloc으로 잘 “빌렸다면”,
이젠 그 공간을 안전하고 효율적으로 활용하는 법을 알아야겠죠?

그럼 지금부터 배열처럼 사용하는 방법부터 구조체, 문자열, 함수 리턴까지
동적 메모리를 실전 예제 중심으로 배워봅시다! 🚀


1. 동적 메모리는 “가변 크기”의 열쇠!

정적 메모리는 컴파일 시 고정되지만,
동적 메모리는 실행 중 필요한 만큼 할당되므로
입력에 따라 크기가 유동적인 구조를 만들 수 있어요.

예를 들어 사용자에게 배열 크기를 입력받고,
그 크기만큼 메모리를 할당해서 쓰는 게 가능하죠!


2. 기본 예제: 동적 배열 사용

c복사편집#include <stdio.h>
#include <stdlib.h>

int main() {
    int n;
    printf("몇 개의 숫자를 입력할까요? ");
    scanf("%d", &n);

    int *arr = (int*) malloc(n * sizeof(int));
    if (!arr) {
        printf("메모리 할당 실패!
");
        return 1;
    }

    // 값 입력 받기
    for (int i = 0; i < n; i++) {
        printf("%d번째 정수: ", i + 1);
        scanf("%d", &arr[i]);
    }

    // 출력
    printf("입력한 정수: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }

    free(arr);
    return 0;
}

📌 사용자가 원하는 크기의 배열을 유연하게 처리할 수 있죠!


3. calloc()으로 초기화된 배열 사용하기

c복사편집int *scores = (int*) calloc(10, sizeof(int));
  • 이 코드는 int 10개의 공간을 0으로 초기화해서 할당합니다.

  • 배열처럼 접근 가능: scores[0], scores[1]

✅ 반복문 없이도 초기값이 0인 배열이 필요한 경우, calloc()이 훨씬 깔끔해요!


4. 문자열 처리: char* 동적 할당

예제: 사용자 입력 문자열 받기

c복사편집#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char temp[100];
    printf("이름을 입력하세요: ");
    fgets(temp, sizeof(temp), stdin);

    char *name = (char*) malloc(strlen(temp) + 1);
    strcpy(name, temp);

    printf("안녕하세요, %s", name);

    free(name);
    return 0;
}

💬 입력 받은 문자열의 길이만큼 정확히 메모리를 할당해 낭비 없이 저장할 수 있어요!


5. 구조체와 동적 메모리

c복사편집typedef struct {
    char *name;
    int age;
} Person;

int main() {
    Person *p = (Person*) malloc(sizeof(Person));

    p->name = (char*) malloc(50);
    strcpy(p->name, "홍길동");
    p->age = 30;

    printf("이름: %s, 나이: %d
", p->name, p->age);

    free(p->name);
    free(p);
    return 0;
}

📌 구조체 멤버 중 문자열처럼 동적 크기를 가진 항목
별도로 malloc()으로 할당해줘야 해요!


6. 2차원 배열처럼 사용하기

c복사편집int **matrix = (int**) malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
    matrix[i] = (int*) malloc(cols * sizeof(int));
}
  • 동적 2차원 배열처럼 사용 가능: matrix[0][1], matrix[i][j]

해제

c복사편집for (int i = 0; i < rows; i++) {
    free(matrix[i]);
}
free(matrix);

✅ 꼭 중첩된 할당 → 중첩된 해제를 기억하세요!


7. 함수에서 동적 메모리 사용하고 반환하기

c복사편집char* getGreeting() {
    char *msg = (char*) malloc(20);
    strcpy(msg, "Hello, World!");
    return msg;
}

int main() {
    char *text = getGreeting();
    printf("%s
", text);
    free(text);
    return 0;
}

🎯 반환된 포인터를 받은 쪽에서 해제를 책임져야 해요!


8. 유의사항 및 메모리 안전 사용 팁

상황

설명

malloc 후 NULL 체크

할당 실패 시 예외 처리

free 후 NULL로 초기화

댕글링 포인터 방지

포인터 덮어쓰기 금지

기존 메모리 손실됨 (누수 발생)

구조체 해제

내부 포인터 멤버도 별도 free() 필요

반복문 할당

반복문 할당 시, 동일하게 반복 free()도 필수


9. 흔한 실수와 방지법

❌ 실수 1: 포인터 덮어쓰기

c복사편집int *ptr = malloc(10);
ptr = malloc(20);  // 첫 번째는 누수!

✅ 해결법:

c복사편집free(ptr);
ptr = malloc(20);

❌ 실수 2: free() 빼먹기

c복사편집void func() {
    int *temp = malloc(100);
    // free(temp); ← 없으면 누수!
}

✅ 해결법: 항상 free()를 같이 작성하는 습관!


❌ 실수 3: 할당 크기 계산 실수

c복사편집int *arr = malloc(10);  // ❌ 10바이트만 할당됨!

✅ 해결법:

c복사편집int *arr = malloc(10 * sizeof(int));  // ✅ 올바른 할당!

✅ 요약 정리

항목

설명

동적 배열

malloc, calloc → 배열처럼 사용

문자열

strlen()만큼 동적 할당 후 복사

구조체

내부 포인터도 별도 할당 필요

함수 반환

동적 메모리 반환 → 사용자가 free()

2차원 배열

행마다 별도로 malloc, free도 각 행별로


마무리하며 💬

동적 메모리는 C 언어에서 가장 강력하면서도 위험한 무기예요!
하지만 올바르게 사용하면 메모리를 낭비하지 않고,
사용자 맞춤형으로 유연한 프로그램을 만들 수 있죠.

🎯 “동적 메모리는 마치 칼과 같다.
잘 쓰면 요리사가 되지만, 잘못 쓰면 손을 다친다.”

다음 시간에는 이 동적 메모리를 좀 더 구조적으로 다룰 수 있는
메모리 풀 기법, 재사용 전략, 그리고 고급 예제들을 함께 공부해봐요!
오늘도 똑똑한 코드, 안전한 메모리! 💻🔥

답글 남기기