프로그래밍Backend C 개발자

C에서 malloc/free를 통해 동적 메모리를 할당, 사용 및 올바르게 해제하는 방법에 대해 자세히 설명하십시오. 동적 메모리 작업 시 어떤 함정이 존재합니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

질문 배경:

동적 메모리 할당 메커니즘은 <stdlib.h>의 malloc/free 함수와 함께 C에서 나타났습니다. 이들은 가변 크기의 구조, 복잡한 컬렉션 및 객체를 구현할 수 있게 하여 언어의 발전과 대규모 프로그래밍에서의 활용에 큰 추진력을 제공했습니다.

문제:

동적 메모리를 작업하려면 프로그래머가 객체의 생명주기를 완벽하게 관리해야 합니다. 오류(메모리 누수, 이중 해제, 포인터의 잘못된 사용)는 시스템 충돌이나 취약점(예: use-after-free 오류를 통한 익스플로잇)을 초래할 수 있습니다.

해결책:

— 항상 malloc/calloc/realloc의 반환 값을 확인하십시오. 할당에 실패하면 NULL을 반환합니다. — 메모리를 해제할 때 포인터를 NULL로 설정하여 해제된 블록을 사용하지 않도록 합니다. — free 후에는 포인터를 사용하지 마십시오. — malloc/free와 calloc/free의 올바른 일치를 유지하십시오.

코드 예:

#include <stdio.h> #include <stdlib.h> int main() { int *arr = malloc(5 * sizeof(int)); if (!arr) { perror("메모리 할당 실패"); return 1; } for (int i = 0; i < 5; ++i) arr[i] = i * i; for (int i = 0; i < 5; ++i) printf("%d ", arr[i]); printf(" "); free(arr); arr = NULL; return 0; }

주요 특징:

  • malloc/calloc/realloc은 void*를 반환하며, 명시적 타입 변환이 필요합니다(단, C++에는 필요하지 않음).
  • free 이후 포인터는 유효하지 않습니다.
  • 할당하는 메모리 크기는 항상 타입과 요소의 수(n * sizeof(type))의 영향을 받습니다.

함정이 있는 질문.

malloc을 통해 할당된 메모리를 delete 연산자를 사용해 해제하면 어떻게 됩니까? 또는 그 반대는 (C++)?

메모리 할당 및 해제 메커니즘을 언어 간(C/C++) 혼합할 수 없습니다. C에서는 오직 malloc/free를, C++에서는 new/delete를 사용해야 합니다.

free(NULL)을 호출하면 어떻게 됩니까?

free(NULL)은 안전합니다(이는 C 표준에서 보장합니다). 이 호출은 아무것도 하지 않습니다.

realloc을 사용하여 메모리 블록을 늘리거나 줄이는 것이 가능하며, 원래 포인터에는 어떤 일이 발생합니까?

realloc은 메모리 블록을 이동시킬 수 있으며, 만약 이동했다면 이전 포인터는 유효하지 않게 됩니다. 항상 새로운 포인터를 할당하십시오:

ptr = realloc(ptr, new_size);

전형적인 오류 및 안티 패턴

  • free 이후 메모리 사용(use-after-free).
  • 동일한 포인터에 대해 double free 호출.
  • 메모리 누수(할당했으나 해제하지 않음).
  • malloc 크기 계산 오류(사이즈를 잊음).
  • 실패한 malloc에 대해 NULL 반환 무시.

실전 사례

부정적 사례

루프에서 배열에 메모리를 할당했지만 반복 끝에서 해제하는 것을 잊습니다. 하룻밤 동안 서버에서 프로그램이 모든 RAM을 "소모"했습니다.

장점:

  • 코드가 간단하고 확인이 적음.

단점:

  • 메모리 누수, 성능 저하, 애플리케이션 충돌.

긍정적 사례

루프에서 항상 사용 후 메모리를 해제하고, malloc 직후에 NULL 확인을 수행하며, 누수를 모니터링하기 위한 디버깅 도구를 사용했습니다.

장점:

  • 안정적인 작동, 누수 없음.
  • 코드 유지보수 및 확장성이 용이함.

단점:

  • 다소 복잡한 코드, 메모리 생명주기 각 단계에서 주의가 필요합니다.