C++에서 메모리 누수 방지

Jinku Hu 2023년10월12일
  1. delete연산자를 사용하여 각할당 메모리 블록을 해제합니다
  2. std::unique_ptr를 사용하여 힙 개체를 자동으로 해제
C++에서 메모리 누수 방지

이 기사에서는 C++에서 메모리 누수를 방지하는 방법에 대한 여러 방법을 보여줍니다.

delete연산자를 사용하여 각할당 메모리 블록을 해제합니다

메모리 누수는 원시 동적 메모리 인터페이스와 직접 상호 작용하는 프로그램의 일반적인 문제이며, 이는 프로그래머가 해당 메서드를 사용하여 할당 된 각 메모리를 해제해야하는 부담을줍니다. C++에서 액세스 할 수있는 메모리 관리를위한 여러 인터페이스가 일부 플랫폼 별 시스템 호출과 함께 제공되며, 이는 기본적으로이 목적에 사용할 수있는 가장 낮은 수준의 기능을 나타냅니다. 대부분의 경우 일반 프로그램은 수동 메모리 관리를 위해newdelete연산자와 같은 언어 별 기능 만 사용하거나 자동 메모리 할당 해제를 위해 스마트 포인터를 사용해야합니다.

메모리 누수의 가장 취약한 방법은new /delete 연산자를 사용하여 힙 메모리를 직접 관리하는 것입니다. new 호출에서 반환 된 모든 포인터는 해당 메모리 블록을 시스템에 돌려 보내기 위하여delete 연산자로 전달되어야한다는 점에주의하십시오. 그렇지 않으면 메모리가 소진 될 수 있습니다. 예를 들어, 다음 프로그램은 10 요소의char 배열을 확보하고 프로그램이 끝날 때까지 그것을 풀어 놓지 않았다. 따라서이 프로그램은 메모리 누수가 있다고 할 수있다.

#include <iostream>

using std::cout;
using std::endl;

constexpr int SIZE = 10;

int main() {
  char *arr = new char[SIZE];

  for (int i = 0; i < SIZE; ++i) {
    arr[i] = (char)(65 + i);
    cout << arr[i] << "; ";
  }
  cout << endl;

  return EXIT_SUCCESS;
}

메모리 누수는 명령 줄 유틸리티이며 컴파일 된 프로그램 파일에서 실행할 수있는valgrind프로그램을 사용하여 감지 할 수 있습니다. Valgrind는 실제로 여러 도구의 집합이며, 그중 하나는 메모리 검사 유틸리티입니다. 메모리 누수를 조사하기 위해 다음 명령을 실행할 수 있습니다.

valgrind --tool=memcheck --leak-check=full ./program

확인이 완료되면 다음 출력이 인쇄됩니다. arr포인터에서delete를 호출하지 않았기 때문에 전체 배열이 해제되지 않은 메모리가되었으므로 누수 요약에서definitely lost: 10 bytes라는 레코드가됩니다. 후자는 10 요소 char 배열의 실제 크기입니다.

==13732== HEAP SUMMARY:
==13732==     in use at exit: 10 bytes in 1 blocks
==13732==   total heap usage: 3 allocs, 2 frees, 73,738 bytes allocated
==13732==
==13732== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==13732==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==13732==    by 0x1091FE: main (tmp.cpp:11)
==13732==
==13732== LEAK SUMMARY:
==13732==    definitely lost: 10 bytes in 1 blocks
==13732==    indirectly lost: 0 bytes in 0 blocks
==13732==      possibly lost: 0 bytes in 0 blocks
==13732==    still reachable: 0 bytes in 0 blocks
==13732==         suppressed: 0 bytes in 0 blocks
==13732==
==13732== For lists of detected and suppressed errors, rerun with: -s
==13732== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

std::unique_ptr를 사용하여 힙 개체를 자동으로 해제

이전 예제 코드 문제는delete [] arr;로 수정할 수 있습니다. 프로그램이 종료되기 전에 문. 그러나 또 다른 옵션은 스마트 포인터 중 하나를 사용하는 것입니다. std::unique_ptr. 스마트 포인터 개체는 지정된 유형으로 초기화 할 수 있으며new연산자에서 반환 된 포인터를 저장합니다. 일반 포인터와의 유일한 차이점은std::unique_ptr관련 메모리 영역이 명시 적으로delete 일 필요가 없다는 것입니다. 대신 컴파일러는 객체가 범위를 벗어나면 할당 해제를 처리합니다.

#include <iostream>
#include <memory>

using std::cout;
using std::endl;

constexpr int SIZE = 10;

int main() {
  std::unique_ptr<char[]> arr(new char[SIZE]);

  for (int i = 0; i < SIZE; ++i) {
    arr[i] = (char)(65 + i);
    cout << arr[i] << "; ";
  }
  cout << endl;

  return EXIT_SUCCESS;
}
작가: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

관련 문장 - C++ Memory