[OS] 메모리 관리 API

장선규·2023년 7월 9일
0

[OS] OSTEP Study

목록 보기
9/28

메모리 관리 API

이번 장에서는 UNIX/C의 메모리 관리 인터페이스에 대해 논의한다.
(여기서의 메모리는 "사용자 주소 공간"을 의미함)

핵심 질문: 어떻게 메모리를 할당하고 관리해야 하는가
일반적으로 어떤 인터페이스가 사용되는가?
어떤 실수를 해서는 안 되는가?

1. 메모리 공간의 종류

C 프로그램이 실행되면 스택 메모리와 메모리에 공간이 할당된다.

  • 이 할당은 프로그래머를 위해 컴파일러가 알아서 암묵적으로 이루어진다.
  • 자동(automatic) 메모리라고도 함

스택 메모리

  • 예를 들어 함수 안에 변수 x 선언하면 스택 메모리에 공간 할당
  • 함수가 종료되면, 컴파일러는 프로그래머 대신에 메모리 반환
  • 함수 리턴 이후 유지되어야 하는 정보는 스택에 저장하지 않는 것이 좋음
    void func(){
    	int x; // 스택에 int 형을 선언
    }

힙 메모리

  • 오랫동안 값이 유지되어야 하는 변수들은 힙 메모리에 저장하면 좋음
  • 모든 할당과 반환이 프로그래머에 의해 명시적으로 처리됨 <- 무거운 책임이 따름
    void func(){
    	int* x = (int*) malloc(sizeof(int));
    }
    • 위의 코드는 스택 할당과 힙 할당 모두 발생
    • 포인터 변수 선언 자체는 스택 영역에 할당
    • malloc()을 오출하여 x를 위한 공간을 할당하는 것은 으로부터 요구
    • 만약 저 상태에서 함수가 종료되면, x에 할당된 메모리 공간이 해제되지 않고 계속 남아있음

2. malloc() 함수

malloc() 함수

#include<stdlib.h> 
...
void* malloc(size_t size);
  • 힙에 요청할 공간의 크기(size)를 넘겨주면, 할당된 공간에 대한 포인터를 사용자에게 반환
  • 할당 실패하면 NULL 반환
  • 보통 size 자리에 sizeof(자료형)가 들어감
  • 문자열을 다룰 때는 malloc(strlen(s) +1)을 해줘서 맨 뒤에 \0을 위한 공간까지 할당함
  • void*형이라 저절로 타입이 변환됨 (type casting)

sizeof() 연산자

  • 메모리의 크기를 바이트 단위로 계산하는 연산자
  • 참고로 sizeof는 함수가 아니고, 컴파일 시간에 값이 결정됨 (함수는 런타임에 값 결정)
    int* ptr = (int*)malloc(10*sizeof(int)); 
    printf(%d\n”,sizeof(ptr)); // -> 4 or 8
    • sizeof(ptr) 이런식으로 포인터를 넣으면, 포인터가 가리키는 놈의 주소가 아닌 포인터 자체의 크기 반환
    int arr[10];
    printf(%d\n”,sizeof(arr)); // -> 40
    • sizeof(arr) 이런식으로 배열을 넣으면, 배열의 크기가 잘 나옴

3. free() 함수

free(): 할당된 힙 메모리를 해제하는 함수

  • malloc()에 의해 반환된 포인터를 인자로 받는다.
  • 할당된 메모리의 크기는 메모리 할당 라이브러리가 알고 있어야 함

4. 흔한 오류

malloc()free() 사용할 때 발생하는 오류들이 많다. C언어는 자동 메모리 관리를 지원하지 않기 때문이다.

자동 메모리 관리(automatic memery management)

  • 주로 new 키워드로 새 객체 할당
  • 메모리 해제는 가비지 컬렉터(GC)가 알아서 해제함

메모리 할당 잊어버리기

  • 메모리 할당했다고 착각함
  • char *dst; 이런식으로 선언만 하고 메모리 할당을 안 하는 경우
  • 세그멘테이션 폴트 (segmentation fault) 발생

메모리를 부족하게 할당받기

  • 메모리를 부족하게 할당받음
  • 버퍼 오버플로우 (buffer overflow)
  • char* src="hello";
    char*dst = (char*)malloc(strlen(src)); // srtlen(src) +1 해줘야함
    strcpy(dst,src); // 동작하기는 하나, 위험```

할당받은 메모리 초기화하지 않기

  • malloc()을 제대로 호출했지만 값 안 넣는것

메모리 해제하지 않기

  • 메모리 누수
  • 메모리가 천천히 누수되면 결국 메모리가 부족하게 되고 시스템을 재시작 해야됨
  • 가비지 컬렉터 있어도 소용 없음, 메모리 청크에 대한 참조가 계속 있기 때문

메모리 사용이 끝나기 전에 메모리 해제하기

  • Dangling pointer
  • free() 호출한 후에 해당 포인터 사용하려고 할 때 발생

반복적으로 메모리 해제하기

  • 이중 해제 (double free) - 결과 예측 어렵

free() 잘못 호출하기

  • free()malloc()이 받은 포인터만 전달될 것으로 예상
  • 근데 그 이외의 값을 전달하면 유효하지 않은 해제 발생

5. 운영체제의 지원

malloc()free()는 시스템 콜이 아니라 라이브러리 함수다.

  • 라이브러리 내의 함수(malloc)가 프로세스 가상 주소 공간을 관리
  • 라이브러리 자체는 시스템 콜을 기반으로 구축

메모리 관련 시스템 콜

  • brk: 프로그램의 break 위치를 변경하는데 사용
    • break는 힙의 마지막 위치를 나타냄
    • brk는 새로운 break 주소를 나타내는 한 개의 인자를 받음
    • 받은 새 주소가 더 크면 힙 영역 늘리고, 작으면 힙 영역 줄임
  • sbrk: 프로그램의 break 위치를 변경하는데 사용 (인자를 증가량으로 받음)
  • mmap(): 프로그램에 annonymous의 메모리 영역을 만듦
    • annonymous 영역은 특정 파일과 연결되어 있지 않고, 스왑 공간(swap space)에 연결된 영역 (나중에 논의)

6. 기타 함수들

  • calloc(): 메모리 할당 영역을 0으로 채워서 반환
  • realloc(): 이미 할당된 공간에 대해 추가 공간이 필요할 때 사용
    • 더 큰 영역을 확보하고, 옛 영역의 내용을 복사한 후에 새 영역에 대한 포인터 반환
profile
코딩연습

0개의 댓글