개발공부

c++ 동적 메모리 할당

Iam_noob 2024. 12. 3. 14:51
728x90
반응형

C++ 동적 메모리 할당 

C++에서의 동적 메모리 할당은 메모리를 효율적으로 사용하고 런타임에 메모리 요구 사항을 충족하기 위해 필수적인 개념입니다. 이번 포스팅에서는 동적 메모리 할당의 기초부터 고급 주제까지 자세히 설명하겠습니다. 

참조: 위키피디아


목차

  1. 동적 메모리 할당이란?
  2. 동적 메모리 할당의 필요성
  3. C++ 동적 메모리 할당 방법
  4. new와 delete 연산자
  5. 배열의 동적 메모리 할당
  6. 동적 메모리 할당의 장점과 단점
  7. 스마트 포인터와 메모리 관리
  8. 동적 메모리 할당 시 발생할 수 있는 문제
  9. C++ 동적 메모리 할당의 실전 예제
  10. 마치며

 

1. 동적 메모리 할당이란?

동적 메모리 할당이란 프로그램 실행 중(runtime)에 메모리를 할당하는 것을 의미합니다. 이는 일반적인 정적 메모리 할당과 대조적이며, 런타임에 메모리의 요구량을 변경할 수 있어 메모리 자원의 효율적인 사용을 가능하게 합니다.

동적 메모리 할당을 사용하면 사용자가 입력한 크기나 프로그램의 실행 환경에 따라 메모리 요구 사항을 결정할 수 있습니다. C++에서는 이를 위해 newdelete 연산자를 사용합니다.

2. 동적 메모리 할당의 필요성

2.1 메모리 사용의 유연성

정적 메모리 할당은 프로그램 작성 시 메모리의 크기를 미리 결정해야 합니다. 그러나 프로그램 실행 중에 정확한 메모리 요구량을 예측하기 어려운 경우가 많습니다. 예를 들어, 사용자가 입력하는 데이터의 크기가 다를 수 있는 상황에서는 정적 할당이 비효율적일 수 있습니다. 동적 메모리 할당은 이러한 문제를 해결할 수 있습니다.

2.2 효율적인 자원 관리

동적 메모리 할당을 통해 필요한 만큼의 메모리만 할당하고 사용 후 해제할 수 있습니다. 이를 통해 메모리 낭비를 줄이고 프로그램의 효율성을 높일 수 있습니다.

3. C++ 동적 메모리 할당 방법

C++에서 동적 메모리 할당은 new 키워드를 사용하여 이루어지며, 할당된 메모리는 더 이상 필요하지 않을 때 delete 키워드를 사용하여 해제합니다. 동적 메모리 할당의 기본 구조는 다음과 같습니다:

int* ptr = new int; // 정수형 메모리 할당
*ptr = 5; // 할당된 메모리에 값 저장

// 사용 후 메모리 해제
delete ptr;

위의 코드에서 new int는 힙(heap) 영역에 메모리를 할당하고, ptr 포인터는 해당 메모리의 주소를 가리킵니다. 메모리를 모두 사용한 후에는 delete를 호출하여 메모리를 해제해야 합니다.

4. new와 delete 연산자

4.1 new 연산자

  • 역할: 힙 영역에 메모리를 할당하고, 해당 메모리의 주소를 반환합니다.
  • 사용법: 단일 변수뿐만 아니라 배열에도 사용할 수 있습니다.
  • 예시:
double* d = new double(3.14); // 값 초기화와 동시에 할당
int* array = new int[10]; // 정수형 배열 메모리 할당

4.2 delete 연산자

  • 역할: new로 할당한 메모리를 해제하여 메모리 누수를 방지합니다.
  • 주의사항: 배열 메모리를 해제할 때는 delete[]를 사용해야 합니다.
  • 예시:
delete d; // 단일 변수 메모리 해제
delete[] array; // 배열 메모리 해제

5. 배열의 동적 메모리 할당

동적 메모리 할당은 단일 변수뿐만 아니라 배열에도 적용할 수 있습니다. 예를 들어 사용자가 원하는 크기의 배열을 동적으로 할당하고 싶은 경우 newdelete[]를 사용할 수 있습니다.

배열 할당 예시

int size;
std::cout << "배열 크기를 입력하세요: ";
std::cin >> size;

int* myArray = new int[size]; // 입력된 크기만큼 배열 할당
for (int i = 0; i < size; i++) {
    myArray[i] = i * 10; // 값 할당
}

// 메모리 해제
delete[] myArray;

이 코드에서는 사용자가 입력한 크기만큼 배열을 동적으로 생성하며, 필요 없는 경우 delete[]로 메모리를 해제합니다.

6. 동적 메모리 할당의 장점과 단점

6.1 장점

  • 메모리 사용의 유연성: 런타임 시점에 메모리 크기를 결정할 수 있어 다양한 입력을 처리할 수 있습니다.
  • 효율적인 메모리 사용: 필요한 만큼만 메모리를 할당하고 사용 후 해제할 수 있습니다.

6.2 단점

  • 복잡성 증가: 메모리 할당 및 해제를 수동으로 관리해야 하므로 코드가 복잡해질 수 있습니다.
  • 메모리 누수: 할당한 메모리를 해제하지 않으면 메모리 누수가 발생하여 시스템 자원을 낭비하게 됩니다.

7. 스마트 포인터와 메모리 관리

C++11 이후에는 스마트 포인터가 도입되어 동적 메모리 관리를 자동화할 수 있게 되었습니다. 스마트 포인터는 사용이 끝나면 자동으로 메모리를 해제해 주므로 메모리 누수 문제를 효과적으로 해결합니다.

주요 스마트 포인터 종류

  • std::unique_ptr: 단일 소유권을 가지며, 다른 포인터와 소유권을 공유할 수 없습니다.
std::unique_ptr<int> uptr = std::make_unique<int>(10);
  • std::shared_ptr: 여러 개의 포인터가 같은 메모리를 공유하며, 참조 횟수가 0이 될 때 메모리를 해제합니다.
std::shared_ptr<int> sptr1 = std::make_shared<int>(20);
std::shared_ptr<int> sptr2 = sptr1; // 같은 메모리를 공유
  • std::weak_ptr: 순환 참조를 방지하기 위해 사용됩니다.

스마트 포인터를 활용한 메모리 누수 방지 팁

  • 스마트 포인터 사용 권장: 일반 포인터 대신 std::unique_ptr 또는 std::shared_ptr을 사용하여 메모리 할당을 자동으로 관리하면, 사용이 끝난 후 자동으로 메모리가 해제되어 메모리 누수를 방지할 수 있습니다.
  • 순환 참조 방지: std::shared_ptr을 사용할 때 두 개 이상의 객체가 서로를 참조하는 상황이 발생하면 참조 횟수가 0이 되지 않아 메모리 해제가 되지 않을 수 있습니다. 이를 방지하기 위해 std::weak_ptr을 사용하여 순환 참조를 끊어줍니다.

8. 동적 메모리 할당 시 발생할 수 있는 문제

8.1 메모리 누수 (Memory Leak)

메모리 누수는 할당한 메모리를 해제하지 않아 시스템 자원이 낭비되는 상황을 의미합니다. 메모리 누수를 방지하기 위해서는 모든 할당된 메모리가 사용 후 delete로 해제되도록 해야 합니다. 스마트 포인터를 사용하면 이러한 문제를 자동으로 해결할 수 있습니다.

8.2 댕글링 포인터 (Dangling Pointer)

해제된 메모리를 참조하는 포인터를 댕글링 포인터라고 합니다. 이는 프로그램의 예기치 않은 동작을 초래할 수 있습니다. 이를 방지하기 위해 포인터를 해제한 후에는 nullptr로 초기화하는 것이 좋습니다.

8.3 잘못된 메모리 접근

포인터가 가리키는 메모리가 할당되지 않았거나 이미 해제된 경우, 잘못된 메모리 접근으로 인해 프로그램이 비정상적으로 종료될 수 있습니다.

9. C++ 동적 메모리 할당의 실전 예제

동적 메모리 할당은 다양한 시나리오에서 사용될 수 있습니다. 다음은 동적 할당을 활용한 간단한 예제입니다.

9.1 학생 성적 관리 프로그램

학생 수를 입력받고 각 학생의 성적을 저장하는 프로그램을 작성할 수 있습니다. 이때 학생 수가 정해지지 않았기 때문에 동적 메모리 할당이 유용합니다.

#include <iostream>
#include <memory>

int main() {
    int numStudents;
    std::cout << "학생 수를 입력하세요: ";
    std::cin >> numStudents;

    // 스마트 포인터를 사용한 동적 메모리 할당
    std::unique_ptr<float[]> scores = std::make_unique<float[]>(numStudents);

    for (int i = 0; i < numStudents; ++i) {
        std::cout << "학생 " << i + 1 << "의 성적: ";
        std::cin >> scores[i];
    }

    float sum = 0;
    for (int i = 0; i < numStudents; ++i) {
        sum += scores[i];
    }
    std::cout << "평균 성적: " << sum / numStudents << std::endl;

    return 0;
}

이 프로그램은 학생 수에 따라 동적으로 배열을 할당하고, 각 학생의 성적을 입력받아 평균 성적을 계산합니다. std::unique_ptr을 사용하여 동적 배열을 관리함으로써 메모리 해제를 자동으로 처리해 메모리 누수의 위험을 줄였습니다.

10. 마치며

동적 메모리 할당은 C++에서 메모리 자원을 효율적으로 관리하고 프로그램의 유연성을 높이는 중요한 기법입니다. newdelete 연산자를 사용하여 메모리를 할당하고 해제하는 기본적인 방법부터 스마트 포인터를 활용한 자동 메모리 관리까지 다양한 방식으로 메모리를 다룰 수 있어야합니다. 이를 잘 활용하면 메모리 누수와 같은 문제를 예방할 수 있을 것 같습니다. 또한 효율적인 프로그램이 될거라 생각 됩니다. 아직 익숙하지 않지만 익숙해 질 때까지 그리고 이를 누군가에게 이해시킬만큼 잘 설명할 수 있을 때까지 익혀야 할 것 같습니다.

728x90
반응형

'개발공부' 카테고리의 다른 글

동기(Synchronous)와 비동기(Asynchronous)  (0) 2024.12.17
자료구조란?  (1) 2024.12.05
인텔리제이(IntelliJ IDEA) 단축키 모음  (6) 2024.11.28
c++ 포인터란?  (0) 2024.11.21
브라우저 작동 방식  (0) 2024.10.16