Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C/C++에서 malloc()과 new()의 차이점 완벽 비교

C와 C++에서는 프로그램 실행 중에 필요한 만큼 메모리를 확보하는 동적 메모리 할당(Dynamic Memory Allocation) 기능을 제공합니다. 대표적인 방식이 바로 C의 malloc() 함수와 C++의 new 연산자입니다. 이 글에서는 두 방식의 문법, 동작 원리, 실제 예제를 통해 차이점을 자세히 살펴보겠습니다.

1. malloc() 함수란?

malloc() 함수는 요청한 크기만큼의 바이트를 메모리에 할당하고, 할당된 메모리 블록의 첫 번째 바이트를 가리키는 포인터를 반환합니다. 메모리 할당에 실패하면 널 포인터(NULL)를 반환하므로, 반드시 반환값을 확인하는 것이 안전한 코딩 습관입니다.

문법

pointer_name = (cast-type*) malloc(size);
  • pointer_name: 포인터 변수에 부여하는 임의의 이름입니다.
  • cast-type: malloc()이 할당한 메모리를 어떤 데이터 타입으로 변환(cast)할지 지정합니다.
  • size: 할당할 메모리 크기를 바이트 단위로 지정합니다.

예제

#include <stdio.h>
#include <stdlib.h>
int main() {
   int n = 4, i, *p, s = 0;
   p = (int*) malloc(n * sizeof(int));
   if(p == NULL) {
      printf("\nError! memory not allocated.");
      exit(0);
   }
   printf("\nEnter elements of array : ");
   for(i = 0; i < n; ++i) {
      scanf("%d", p + i);
      s += *(p + i);
   }
   printf("\nSum : %d", s);
   return 0;
}

실행 결과

Enter elements of array : 32 23 21 8
Sum : 84

위 프로그램에서는 네 개의 변수를 선언했으며, 그중 포인터 변수 *pmalloc()으로 할당받은 메모리 주소를 저장합니다. 이후 배열 요소 4개를 입력받아 합계를 출력하는 구조입니다.

int n = 4, i, *p, s = 0;
p = (int*) malloc(n * sizeof(int));
if(p == NULL) {
   printf("\nError! memory not allocated.");
   exit(0);
}
printf("\nEnter elements of array : ");
for(i = 0; i < n; ++i) {
   scanf("%d", p + i);
   s += *(p + i);
}
printf("\nSum : %d", s);

여기서 핵심 포인트는 다음과 같습니다.

  • n * sizeof(int): 정수형 변수 4개가 들어갈 만큼의 크기를 바이트 단위로 계산합니다.
  • (int*): void 포인터로 반환되는 값을 int 포인터로 명시적으로 형변환합니다.
  • NULL 검사: 할당 실패 여부를 확인해야 런타임 오류를 예방할 수 있습니다.

2. new 연산자란?

C++의 new 연산자는 힙(heap) 영역에 메모리 할당을 요청합니다. 충분한 메모리가 남아 있다면 해당 메모리를 초기화한 후 포인터 변수에 저장하고 그 주소를 반환합니다. malloc()과 달리 객체 생성 시 생성자를 자동으로 호출한다는 점이 큰 특징입니다.

기본 문법

pointer_variable = new datatype;

초기화를 함께 수행하는 문법

pointer_variable = new datatype(value);

메모리 블록(배열)을 할당하는 문법

pointer_variable = new datatype[size];

예제

#include <iostream>
using namespace std;
int main () {
   int *ptr1 = NULL;
   ptr1 = new int;
   float *ptr2 = new float(223.324);
   int *ptr3 = new int[28];
   *ptr1 = 28;
   cout << "Value of pointer variable 1 : " << *ptr1 << endl;
   cout << "Value of pointer variable 2 : " << *ptr2 << endl;
   if (!ptr3)
   cout << "Allocation of memory failed\n";
   else {
      for (int i = 10; i < 15; i++)
      ptr3[i] = i+1;

      cout << "Value to store in block of memory: ";
      for (int i = 10; i < 15; i++)
      cout << ptr3[i] << " ";
   }
   return 0;
}

실행 결과

Value of pointer variable 1 : 28
Value of pointer variable 2 : 223.324
Value to store in block of memory: 11 12 13 14 15

위 프로그램에서는 세 개의 포인터 변수 ptr1, ptr2, ptr3를 선언했습니다. ptr1ptr2new를 사용해 값을 초기화하며, ptr3new로 할당한 메모리 블록(정수 28개 크기의 배열)의 시작 주소를 저장합니다.

ptr1 = new int;
float *ptr2 = new float(223.324);
int *ptr3 = new int[28];
*ptr1 = 28;

3. malloc()과 new의 주요 차이점 정리

두 방식의 특징을 한눈에 비교할 수 있도록 정리하면 다음과 같습니다.

구분malloc()new
종류C 표준 라이브러리 함수C++ 연산자
반환 타입void* (명시적 형변환 필요)해당 타입의 포인터 (형변환 불필요)
초기화불가능 (쓰레기 값 유지)가능 (생성자 호출)
생성자/소멸자 호출호출하지 않음자동으로 호출
할당 실패 시NULL 반환bad_alloc 예외 발생
메모리 해제free()delete / delete[]

결론적으로, C 언어 환경이나 저수준 제어가 필요한 경우에는 malloc()free() 조합을, C++에서는 생성자·초기화·타입 안전성 측면에서 유리한 newdelete 조합을 사용하는 것이 좋습니다. C++11 이상에서는 더욱 안전한 스마트 포인터(std::unique_ptr, std::shared_ptr) 활용도 고려해 보세요.