티스토리 뷰

자 이번 포스팅에서는 C/C++ 면접 시 단골질문으로 나오는 C/C++의 동적할당 부분에 대해서 포스팅해 보겠습니다.

 

먼저 동적 할당이란 프로그램 실행 중에 필요한 메모리를 할당하는 것을 말합니다.반면에 정적 할당은 프로그램이 실행되기 전에 메모리를 할당하는 방법을 말하며, 변수 선언과 같이 컴파일 타임에 메모리 공간이 확정됩니다.

 

C/C++에서는 동적 할당을 위해 malloc/calloc/realloc 함수(C) 또는 new/delete 연산자(C++)를 사용합니다. 

 

동적 할당과 정적 할당의 가장 큰 차이점은 할당 시점메모리 영역입니다.

 

할당 시점: 정적 할당은 컴파일 타임에, 동적 할당은 런타임에 메모리를 할당합니다. 이로 인해 동적 할당은 프로그램이 실행 중에도 메모리를 필요에 따라 할당하거나 해제할 수 있으며, 이는 유연성을 제공합니다.


메모리 영역: 정적 할당은 스택 메모리에, 동적 할당은 힙 메모리에 이루어집니다. 스택 메모리는 함수 호출이 이루어질 때 생성되고 함수가 종료되면 사라지는 반면, 힙 메모리는 프로그래머에 의해 직접 관리되므로 메모리의 생명주기를 제어할 수 있습니다.

C언어의 malloc/free

C언어에서 동적 메모리 할당은 malloc 함수를 이용하여 이루어집니다. malloc은 메모리의 크기를 바이트 단위로 입력받아, 해당 크기만큼의 메모리를 할당하고 그 시작 주소를 반환합니다. 반면에, 메모리 해제는 free 함수를 이용합니다. free 함수는 malloc으로 할당받은 메모리의 주소를 입력받아, 해당 메모리를 해제합니다.

int *ptr = (int*)malloc(sizeof(int) * 5); // 메모리 할당
free(ptr); // 메모리 반환

C++의 new/delete

C++에서 동적 메모리 할당은 new 연산자를 통해 이루어집니다. new는 객체의 타입을 기반으로 메모리를 할당하고, 해당 객체의 주소를 반환합니다. 반면에, 메모리 해제는 delete 연산자를 이용합니다. delete는 new로 할당받은 메모리의 주소를 입력받아, 해당 메모리를 해제합니다.

int *ptr = new int[5]; // 메모리 할당 및 객체 생성
delete[] ptr; // 객체 소멸 및 메모리 반환

C언어의 malloc/free와 C++의 new/delete 차이

차이점 1: 초기화

malloc은 메모리를 할당만 하며, 초기화는 하지 않습니다. 반면, new는 메모리를 할당하고 초기화까지 진행합니다.

int* ptr1 = new int; // 초기화 됨
int* ptr2 = (int*) malloc(sizeof(int)); // 초기화 되지 않음

주의할 점: 초기화되지 않은 메모리를 사용하면 예상치 못한 결과를 초래할 수 있으므로, 항상 초기화를 해주는 것이 좋습니다


 

차이점 2: 예외 처리

new는 메모리 할당 실패 시, bad_alloc 예외를 발생시킵니다. 반면에, malloc은 메모리 할당 실패 시, NULL을 반환합니다.

try {
    int* ptr = new int; // 메모리 할당에 실패하면 bad_alloc 예외 발생
} catch (std::bad_alloc& e) {
    std::cout << "allocation failed: " << e.what();
}

int* ptr = (int*) malloc(sizeof(int)); // 메모리 할당에 실패하면 NULL 반환
if (ptr == NULL) {
    printf("allocation failed\n");
}

주의할 점: 메모리 할당 실패 시, 적절한 처리를 해주지 않으면 프로그램이 예상치 못하게 종료될 수 있습니다. 따라서 메모리 할당 후 반드시 확인을 해야 합니다.


차이점 3: 타입 캐스팅

malloc은 반환 값이 void* 타입이므로, 사용하려는 타입으로 캐스팅해주어야 합니다. 반면에, new는 해당 타입의 포인터를 반환합니다.

int* ptr1 = new int; // 타입 캐스팅 없음
int* ptr2 = (int*) malloc(sizeof(int)); // 타입 캐스팅 필요

주의할 점: 타입 캐스팅 없이 void* 타입을 사용하면 예상치 못한 결과를 초래할 수 있습니다.


차이점 4: 연산자 오버로딩

 

C++의 new와 delete는 연산자이기 때문에 연산자 오버로딩이 가능합니다. 즉, 클래스나 객체에 대해 new와 delete의 동작을 재정의할 수 있습니다. 이는 객체 지향 프로그래밍에 있어서 유용하게 사용될 수 있습니다. 반면에, C의 malloc과 free는 함수이기 때문에 이와 같은 연산자 오버로딩이 불가능합니다.

class MyClass {
public:
    void* operator new(size_t size) {
        cout << "new operator overloading" << endl;
        void* p = malloc(size);
        return p;
    }

    void operator delete(void* p) {
        cout << "delete operator overloading" << endl;
        free(p);
    }
};

MyClass* obj = new MyClass(); // "new operator overloading" 출력
delete obj; // "delete operator overloading" 출력

주의할 점: 연산자 오버로딩을 잘못 사용하면 프로그램의 오해를 살 수 있으므로, 반드시 필요한 경우에만 사용해야 합니다.


차이점 5: 객체 생성과 소멸

 

C++의 new는 객체의 메모리를 할당할 뿐만 아니라 생성자를 호출하여 객체를 초기화하고, delete는 소멸자를 호출하여 객체를 소멸시킵니다. 따라서, C++의 new/delete는 객체 지향 프로그래밍에 더 적합합니다. 반면에, C의 malloc/free는 단순히 메모리를 할당하고 해제하는 역할만 수행하므로, 객체의 생성과 소멸에 대한 처리를 직접 해주어야 합니다.

class MyClass {
public:
    MyClass() {
        cout << "Constructor" << endl;
    }
    ~MyClass() {
        cout << "Destructor" << endl;
    }
};

MyClass* obj = new MyClass(); // "Constructor" 출력
delete obj; // "Destructor" 출력

주의할 점: 생성자와 소멸자가 호출되지 않는 상황에서 객체를 사용하면 예상치 못한 결과를 초래할 수 있습니다. 따라서 객체의 생명주기를 잘 고려하여 코드를 작성해야 합니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함