동적 메모리 할당기는 Heap이라고 하는 프로세스의 가상메모리 영역을 관리한다.
가용 블록은 응용이 명시적으로 할당할 때 까지 가용 가능한 상태로 남아있다. 할당된 블록은 응용에 의해 명시적(malloc - free)으로, 또는 메모리 할당기 자신에 의해 묵시적으로 반환(가비지 콜렉션)될 때까지 할당된 채로 남아있다.
malloc 함수는 블록 내에 포함될 수 있는 어떤 종류의 데이터 객체에 대해서 적절히 정렬된 최소 size 바이트를 갖는 메모리 블록의 포인터를 리턴한다.
프로그램이 할당 가능한 가상메모리보다 더 큰 크기의 메모리 블록을 요청하는 등의 문제를 만난다면 malloc은 NULL을 리턴하고 errno를 설정한다.
calloc은 초기화된 동적메모리를 할당할 때 사용할 수 있고, 할당된 블록의 크기를 변경하려면 realloc함수를 사용할 수 있다.
할당된 힙 블록은 free 함수를 통해 반환된다.
프로그램을 실제로 실행시키기 전에는 자료 구조의 크기를 알 수 없는 경우에 유용하다.
가용 메모리가 할당 요청을 만족시킬 정도로 가용되지 않았을 때 일어나는 현상이다.
1. 내부 단편화
할당된 블록이 데이터 자체보다 더 클 때 일어난다. 내부 단편화는 정량화하기 간단하다.
2. 외부 단편화
할당요청을 만족시킬 수 있는 메모리 공간이 전체적으로는 충분하지만, 이 요청을 처리할 수 있는 단일한 가용블록은 없는 경우 발생한다.
이를 측정하기 어려운 이유는 외부 단편화는 미래의 요청 패턴에 의해서도 발생할 수 있기 때문이다.
외부 단편화가 측정하기 어렵고 예측 불가능하기 때문에 할당기들은 더 적은 수의 더 큰 가용블록들을 유지하려는 방법을 채택하고 있다.
first fit
가용 free 리스트를 처음부터 검색해서 크기가 맞는 첫 번째 가용 블록을 선택한다.
장점은 리스트의 마지막에 가장 큰 가용 블록들을 남겨두는 경향이 있다.
단점은 리스트의 앞 부분에 작은 가용 블록들을 남겨두는 경향이 있어서 큰 블록을 찾을 때 시간이 걸린다.
next fit
검색을 리스트의 처음부터 시작하는 대신, 이전 검색이 종료된 지점에서 검색을 시작한다.
장점은 first fit에 비해 매우 빠른 속도를 가진다.
단점은 first fit 보다 최악의 메모리 이용도를 가질 수 있다.
best fit
모든 가용블록을 검사하며 크기가 맞는 가장 작은 블록을 선택한다.
장점은 더 좋은 메모리 이용도를 갖는다.
단점은 힙을 완전히 다 검색해야 한다는 것이다.
포인터가 의미있는 데이터가 존재하지 않는 곳을 참조하게 되면 운영체제는 이 프로그램을 segmentation 예외로 종료한다. 또는 read-only 인 곳에 데이터를 쓰려고 할 때 보호 예외로 프로그램이 종료된다.
scanf 함수에 변수의 주소를 전달하는 대신 변수를 썼을 때도 이러한 오류가 일어날 수 있다.
힙 메모리는 동적할당 되었을 때 자동으로 초기화 되지 않는다. 이를 위해선 calloc을 이용해 0으로 초기화를 시켜야 한다.
입력되는 스트링의 길이를 조사하지 않고 스택상의 타깃 버퍼에 쓰려고 한다면
(즉 할당되는 메모리의 크기보다 더 큰 길이의 문자열이 들어온다면) 이 프로그램은 버퍼 오버플로우 버그를 갖게 된다.
포인터는 어떤 데이터타입을 받더라도 일정한 크기를 갖게 되지만, 그 포인터가 가리키는 데이터 타입인 타입에 따라 크기가 제각각이다.
할당된 바이트의 크기보다 더 큰 자료형의 데이터가 덮어씌워질 때 발생하는 에러
포인터가 가리키는 정수 값 대신에 포인터 자신을 감소시키는 경우가 있다.
(size) -- 대신에 size --라고 쓰는 경우, --와 *의 우선순위가 동일하기 때문에 연산은 우에서 좌로 발생하게 되고 결국 포인터가 참조하는 값이 아닌 포인터의 값이 감소한다.
포인터에 대한 산술 연산은 이들이 가리키는 객체의 크기 단위로 수행된다는 것이다.
지역변수를 가리키는 포인터를 리턴하고 함수 밖으로 나가면, 포인터 자체는 어떤 주소를 담고 있겠지만 그 주소에 있는 지역변수의 값은 더이상 유효하지 않다.
이미 반환한 힙 블록 내에 데이터를 참조하면 에러가 발생한다.
할당된 블록을 반환하는 것을 잊어서 힙에 가비지가 생겨났을 때 일어나는 현상이다.