가상 메모리 영역을 저수준의 mmap(생성)과 munmap(삭제) 함수를 사용해서 생성하고 삭제 가능
C programmer들은 대개 추가적인 가상메모리를 런타임에 획득할 필요가 있을 때, 동적 메모리 할당기(dynamic memory allocator)를 사용하는 것을 좀 더 편리하고 호환성이 좋다고 생각
동적 메모리는 heap이라고 하는 프로세스의 가상메모리 영역에 할당됨
동적 메모리 할당을 사용하는 가장 중요한 이유
프로그램을 실제 실행시키기 전에는 자료 구조의 크기를 알 수 없는 경우들이 있기 때문에
allocator 는 두 가지 basic style을 가지고 있음.
두 style 모두 applicatin 이 explicitly allocate block을 할당하도록 요구함
두 style의 차이는 할당된 block을 해제하는데 있음.
- explicit allocator는 application이 할당된 블록을 return 해줄 것을 요구함
- C 표준 라이브러리는 malloc 패키지라고 하는 명시적 할당기를 제공
- malloc으로 할동하고 free로 block을 반환
- C++는 new와 delete로 사용
- implicit allocator 는 할당된 블록이 program에 의해 더 이상 사용되지 않을 때를 감지하고 block을 해제함
- implicit allocator는 garbage collector(사용하지 않는 할당된 블록을 자동으로 반환시켜주는 작업) 라고 알려져있음
- List, ML, Java 등은 할당된 블록들을 반환시키기 위해서 garbage collection을 사용함
32bit - 8의 배수인 block을 return
64bit - 16의 배수인 block을 retrun
✔ malloc은 return하는 메모리를 초기화하지 않음
초기화가 필요하다면 calloc을 사용 (calloc은 동적메모리 기능 + 값을 0 으로 초기화 해줌)
✔ 이전에 할당된 block의 크기를 변경하려면 realloc을 사용
Dynamic memory allocator는 mmap과 munmap 함수를 사용해서 heap memory를 할당하거나 반환, sbrk 함수도 사용가능
mmap : dynamic memory 할당
munmap : dynamic memory 해제
sbrk : 할당된 memory 증감 - 정상동작하면 brk의 이전 주소 값을 return하고 실패하면 -1을 return 함
sbrk는 brk 포인터에 increase를 더해서 heap을 늘리거나 줄임
- 즉, brk로 할당했을때 받은 주소 값은 그대로이고 공간의 크기만 바뀐다
- 따라서, brk의 이전 주소 값과 동일한 주소 값을 return 받는 것
free 함수
free 함수는 mallco, calloc, realloc에서 할당된 block의 시작되는 부분을 ptr로 받음
시작 부분을 받지 않으면 정상 동작하지 않음
free 함수의 안좋은 점은 잘못되더라도 return 값이 나오지 않기 때문에 확인할 수 없음
위 그림 설명
처음에 heap은 18워드를 할당 받고 더블 워드로 정렬됨
a : 4개의 워드를 할당함. 그리고, P1 은 할당된 block의 첫 부분을 가리킴
b : 5개의 워드를 요청하였으나 더블 워드로 정렬이 되어야하기 때문에 추가적인 워드를 패딩하여 6개를 할당함. 그리고, P2는 두번째로 할당한 block의 첫 부분을 가리킴
c : 6개의 워드를 요청하고 6개의 워드를 할당 받음
d : p2로 할당 받은 block을 free함. 하지만 포인터 P2는 여전히 남아있음, P2가 새로운 malloc 콜에 의해 다시 초기화될 때까지 P2를 사용하지 않는 것은 application 의 responsibility임
e : 2개의 할당을 요청하고 P2가 free된 부분부터 다시 채워나감
- malloc은 모든 데이터를 더블 워드로 정렬한다. (메모리 크기 X 메모리 주소 O)
- 이에 따라 모든 반환되는 메모리 주소가 더블 워드의 배수가 된다.
- 이렇게 동작하는 이유는 input 되는 데이터의 크기를 예상할 수 없기 때문에 모든 경우의 수에 대응하기 위해서 더블워드의 배수를 할당하는 것이다.
질문 내용과 답변 저장
(질문)9.9 동적메모리 할당 811 page의 그림 9.34에 해당하는 내용입니다.
그림 9.34(b)에서 더블워드 경계에 정렬되도록 하기 위해서 블록에
추가적인 워드를 패딩하였다 부분입니다.
그림에 따르면 4워드, 5워드로 9워드를 할당 받고 10번째 워드를 패딩한 후
11번째 워드부터 다시 블록을 할당 받는 모습을 보여줍니다.
여기서 패딩이 이뤄지는 이유가 더블 워드로 정렬이 되기 때문에
5 워드 블록을 요청한 것을 패딩을 포함한 6워드로 할당되는 것이 맞는지 알고 싶습니다.
혹시 제가 맞게 생각을 하는 것인지 알고 싶습니다.
(답변)패딩이 이뤄지는 이유가 더블 워드로 정렬이 되기 때문인지 질문 주셨는데,
제가 질문을 이해하기론 인과 관계가 거꾸로 된 것 같습니다.
정확히 설명하자면, malloc이 항상 더블 워드로 정렬된 메모리 주소를
반환하기 위해서 패딩을 합니다.
Section 3.9.3의 data alignment 부분에 보면 데이터 타입에 따른 alignment 요구사항이 있는데,
malloc함수 자체는 사용자가 이 메모리 주소에 어떠한 데이터를 저장할 지 모르기 때문에
더블 워드의 배수만큼의 크기를 할당해 줌으로써 모든 경우에 대응할 수 있게 해줍니다.
(만약 (b)에서 패딩을 안하면 p3이 할당받은 메모리 주소에 long이나 double을 저장한다고 했을 때
alignment requirement에 맞지 않게 될 겁니다)
(질문)아 그러면
요청된 블록을 더블워드로 정렬하기 위해서
패딩을 하는 것이 아닌 malloc은 더블 워드로 정렬된 메모리 주소를 반환하기
때문에 5워드로 요청된 블록을 패딩을 포함한 6워드로 할당한다 가 맞다는 말씀이신가요?
또한 data alignment는 메모리 주소에 어떤 데이터를 저장할지
예상할 수 없기 때문에 모든 경우의 수에 대응할 수 있도록 더블 워드의 배수를 할당한다.
라고 이해하였는데 맞을까요?
(답변)1. malloc이 요청된 블록을 더블워드로 정렬하기 위해서 패딩을 한다는 전자의 설명이 맞는 것 같습니다.
더블워드로 정렬한다는 말은 반환하는 메모리의 크기가 더블워드의 배수라는 말이 아니고
반환하는 메모리 주소가 더블워드의 배수가 되어야 한다는 말인데,
(b)에서 패딩을 해주면 다음 malloc call에서 쉽게 memory alignment에
맞는 메모리 주소를 반환할 수 있기 때문에 이러한 design choice를 합니다.
2. 네 맞습니다.