들어가기 전에
메모리를 할당한 후에 저장한 값이 필요가 없어지고 나서는 어떻게 해야 할까요? 유한한 메모리를 효과적으로 관리하기 위해서 우리가 프로그램을 작성하며 할당한 많은 메모리들을 어떻게 관리해야 하는지에 대해 배워보겠습니다.
학습 목표
메모리를 할당하고 해제할 수 있습니다.
핵심 단어
- free
- valgrind
강의 듣기
들어가기 전에
메모리를 할당한 후에 저장한 값이 필요가 없어지고 나서는 어떻게 해야 할까요? 유한한 메모리를 효과적으로 관리하기 위해서 우리가 프로그램을 작성하며 할당한 많은 메모리들을 어떻게 관리해야 하는지에 대해 배워보겠습니다.
학습 목표
메모리를 할당하고 해제할 수 있습니다.
핵심 단어
강의 듣기
malloc 함수를 이용하여 메모리를 할당한 후에는 free라는 함수를 이용하여 메모리를 해제해줘야 합니다.
그렇지 않은 경우 메모리에 저장한 값은 쓰레기 값으로 남게 되어 메모리 용량의 낭비가 발생하게 되기 때문이죠.
이러한 현상을 ‘메모리 누수’라고 일컫습니다.
valgrind 라는 프로그램을 사용하면 우리가 작성한 코드에서 메모리와 관련된 문제가 있는지를 쉽게 확인할 수 있습니다.
help50 valgrind ./filename
와 같은 명령어를 사용하면 filename 파일에 대한 valgrind의 검사 내용을 쉽게 확인할 수 있습니다.
아래와 같은 코드가 있다고 생각해봅시다.
#include <stdlib.h>
void f(void)
{
int *x = malloc(10 * sizeof(int));
x[10] = 0;
}
int main(void)
{
f();
return 0;
}
f 함수를 살펴보면 먼저 포인터 x에는 int형의 사이즈(4바이트)에 10배에 해당하는 크기의 메모리, 즉 40바이트를 할당합니다.
그리고 x의 10번째 값으로 0을 할당합니다.
그리고 main 함수에서 f를 실행하게 되는데, 이 코드를 valgrind 로 검사해보면 버퍼 오버플로우와 메모리 누수 두 가지 에러를 확인할 수 있습니다.
먼저 버퍼 오버플로우는 x[10] = 0; 코드로 인해 발생합니다.
우리는 10개의 int형의 배열을 만들었는데 배열의 인덱스가 0부터 시작한다는 점을 감안하면 인덱스 10은 11번째 인덱스에 접근하겠다는 의미이고, 이는 정의되지 않은 것이기 때문에 버퍼 오버플로우가 발생하는 것이죠.
따라서 이 오류는 0에서 9 사이의 인덱스를 사용하면 해결할 수 있습니다.
또한 메모리 누수는 x라는 포인터를 통해 할당한 메모리를 해제하기 위해 free(x) 라는 코드를 추가해줌으로써 해결할 수 있습니다.
생각해보기
제한된 메모리를 가지고 프로그래밍을 할 때 메모리를 해제하지 않으면 어떤 문제가 발생할 수 있을까요?
comment
메모리 누수(프로그램이 동적으로 할당한 메모리를 해제하지 않아서 사용하지 않는 메모리가 시스템에 계속 점유되는 현상)로 프로그램을 사용할 수 없게 되고 시스템 성능이 저하된다.
낭비되는 메모리로 인해 정작 중요한 데이터를 저장하지 못 할 수 있다.
메모리 누수 발생으로 메모리 부족 및 시스템 성능 저하 문제가 발생함
메모리 누수를 요인으로 하는 다양한 문제를 야기할 수 있다.
1. 메모리 부족
2. 성능 저하
1. 메모리 부족
메모리 누수가 지속되면 시스템의 사용 가능한 메모리가 점점 줄어들어 결국 메모리가 부족해질 수 있어. 이는 프로그램이 더 이상 메모리를 할당받을 수 없게 되어 비정상적으로 종료되거나 시스템 전체의 성능이 저하될 수 있어.
2. 성능 저하
메모리 누수가 발생하면 시스템의 메모리 관리가 복잡해지고, 메모리 부족으로 인해 디스크 스와핑이 발생할 수 있어. 이는 프로그램의 실행 속도를 느리게 하고 전체 시스템의 성능을 저하시킬 수 있어.
3. 프로그램 충돌
메모리 누수가 심각해지면 프로그램이 비정상적으로 종료되거나 충돌할 수 있어. 이는 특히 중요한 시스템이나 서비스에서 큰 문제가 될 수 있어.
4. 리소스 낭비
메모리 누수는 시스템 리소스를 낭비하게 만들어, 다른 프로그램이나 프로세스가 필요한 메모리를 할당받지 못하게 할 수 있어.
사용한 메모리를 해제하지 않으면, 이러한 메모리들이 쌓여서 메모리 낭비가 발생하며
이로인해 프로그램이 동작을 멈추거나 여러 버그가 발생하는 등의 문제점이 발생할 수 있습니다.
메모리 부족 상황에 처할 수 있습니다.
메모리 누수가 발생한다. 컴퓨터 내의 메모리는 한정적이므로 비효율적이다.
메모리 누수
-> 유한한 메모리를 비효율적으로 사용하게 됨
결국 '제한'된 메모리이기 때문에, 더이상 사용가능한 메모리가 없어지게 될 수 있다.
메모리를 제대로 해제하지 않으면 메모리 누수가 발생함 이는 프로그램이 동적으로 할당한 메모리를 반환하지 않고 계속 사용하는 상황을 나타낸다.
메모리 누수는 메모리 부족을 야기하여 프로그램이 중단될 수 있으며, 프로그램의 성능이 저하된다. 또한 예기치 못한 동작으로 버그가 발생할 수 있으며, 전체 시스템의 전반적인 안정성을 저해하여 더 나아가 다른 프로그램에도 영향을 미칠 수도 있다.
메모리 누수가 발생하고 메모리가 꽉 차게 되면 오류가 발생
line 6에 x[9] = 10; 을 *(x+9) = 10; 으로 표현법을 바꿔도 에러가 나지 않는데, 두 코드가 같은 의미겠죠?
메모리 누수가 발생한다
메모리 누수가 발생하고 메모리가 꽉 차게 되면 오류가 발생할 수 있다.
메모리 누수가 발생해, 수행해야할 기능들이 수행되지 않거나, 프로그램의 실행 및 연산속도가 느려집니다.
malloc과 같은 함수로 메모리를 할당했을때는 free 함수를 통해 메모리를 해제해줘야 합니다. 그렇지 않으면 메모리 누수가 발생되어 메모리 낭비와 나중에 메모리가 가득 차게 되면 오류가 발생 될 수 있습니다.
메모리 누수 문제가 발생하여 쓸 수 있는 메모리가 줄어들어 정작 메모리가 필요할때 쓰지 못하는 메모리 부족의 문제를 발생시킬 수 있습니다.
ChatGPT:
1. 메모리 누수 (Memory Leak):
동적으로 할당된 메모리를 해제하지 않으면 해당 메모리 블록이 계속 남아 있게 됩니다. 이러한 상태를 메모리 누수라고 합니다. 메모리 누수는 프로그램 실행 중에 사용 가능한 메모리 공간이 줄어들고, 메모리 공간이 부족해지면서 프로그램의 성능이 저하되고 오류가 발생할 수 있습니다. 장기적으로 실행되는 프로그램에서는 메모리 누수로 인해 시스템 전체의 성능에 영향을 미칠 수도 있습니다.
2. 잘못된 포인터 참조 (Dangling Pointers):
메모리를 해제하지 않고 해당 메모리 블록을 가리키는 포인터가 존재하는 경우, 이를 dangling pointer라고 합니다. dangling pointer는 더 이상 유효한 메모리를 가리키지 않으므로 이후에 이를 참조하려고 시도하면 예기치 않은 동작이 발생할 수 있습니다. 프로그램이 dangling pointer를 역참조하려는 경우, 런타임 오류인 "undefined behavior"가 발생할 수 있습니다. 이는 예측할 수 없는 동작을 포함하여 다양한 문제를 일으킬 수 있습니다.
3. 메모리 손상 (Memory Corruption):
동적으로 할당된 메모리를 해제하지 않고 다른 메모리 영역을 덮어쓰는 경우, 해당 메모리 영역에 저장된 데이터가 손상될 수 있습니다. 이로 인해 예기치 않은 결과가 발생하거나 프로그램이 오작동할 수 있습니다. 메모리 손상은 디버깅이 어려운 버그를 유발할 수 있으며, 보안 취약점으로 이어질 수도 있습니다.
4. 리소스 누수 (Resource Leak):
메모리 외에도 파일 핸들, 네트워크 연결, 락 등 다른 리소스도 할당 및 해제되어야 합니다. 이러한 리소스들을 해제하지 않으면 리소스 누수가 발생하고, 시스템 자원의 고갈이나 다른 프로세스에 영향을 줄 수 있습니다. 예를 들어, 파일을 열었는데 프로그램이 종료되기 전에 파일을 닫지 않는다면, 시스템의 파일 디스크립터가 고갈되어 파일
적절히 해제하지 않은 메모리는 계속 공간을 차지하므로 전체적으로 메모리 낭비가 심한 프로그램을 만들게 됩니다.
또한 해제하지 않은 영역의 데이터에 접근해 보안 문제를 야기할 가능성도 있습니다.