Foo* set = new Foo[100];
// ...
delete [] set;
배열의 경계를에 전달하지 않습니다 delete[]
. 그러나 그 정보는 어디에 저장되어 있습니까? 표준화 되었습니까?
Foo* set = new Foo[100];
// ...
delete [] set;
배열의 경계를에 전달하지 않습니다 delete[]
. 그러나 그 정보는 어디에 저장되어 있습니까? 표준화 되었습니까?
답변:
힙에 메모리를 할당하면 할당자는 할당 한 메모리 양을 추적합니다. 이것은 일반적으로 할당 된 메모리 직전에 "헤드"세그먼트에 저장됩니다. 그렇게하면 메모리를 비울 때 할당 해제자는 메모리를 얼마나 비울 수 있는지 정확히 알 수 있습니다.
free
할당 할 메모리 양을 알고있는 방법"입니다. 예, 메모리 블록 크기는 "어딘가"에 의해 malloc
(일반적으로 블록 자체에) 저장되므로 free
알 수 있습니다. 그러나 new[]
/ delete[]
는 다른 이야기입니다. 후자는 기본적으로 malloc
/ 위에서 작동합니다 free
. new[]
또한 메모리 블록에 생성 된 요소 수 (와 독립적으로 malloc
)를 저장하므로 나중에 delete[]
해당 숫자를 검색하고 사용하여 적절한 수의 소멸자를 호출 할 수 있습니다.
malloc
) 및 요소 개수 (by new[]
)). 일반적으로 메모리 블록의 크기가 요청 된 크기의 배열에 실제로 필요한 것보다 클 수 있기 때문에 전자는 후자를 계산하는 데 사용할 수 없습니다. 또한 배열 요소 카운터는 사소한 소멸자가없는 유형에만 필요합니다. 사소한 소멸자가있는 유형의 경우 카운터는에 의해 저장 new[]
되지 않으며 물론에 의해 검색되지도 않습니다 delete[]
.
컴파일러의 접근법 중 하나는 조금 더 많은 메모리를 할당하고 헤드 요소에 요소 수를 저장하는 것입니다.
수행 방법 예 :
여기
int* i = new int[4];
컴파일러는 sizeof(int)*5
바이트 를 할당 합니다.
int *temp = malloc(sizeof(int)*5)
첫 sizeof(int)
바이트 에 "4"를 저장 합니다
*temp = 4;
그리고 설정 i
i = temp + 1;
따라서 i
5가 아닌 4 개의 요소로 구성된 배열을 가리 킵니다.
그리고 삭제
delete[] i;
다음과 같은 방식으로 처리됩니다.
int *temp = i - 1;
int numbers_of_element = *temp; // = 4
... call destructor for numbers_of_element elements
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed
free (temp)
C ++ 표준에서 컴파일러에 따라 정의됩니다. 이것은 컴파일러의 마술을 의미합니다. 하나 이상의 주요 플랫폼에서 사소한 정렬 제한으로 인해 중단 될 수 있습니다.
에 의해 delete[]
반환 된 포인터에 대해서만 정의되며 new[]
,에 의해 반환 된 포인터와 같지 않을 수 있음을 인식함으로써 가능한 구현에 대해 생각할 수 있습니다 operator new[]
. 와일드에서 한 구현은에서 반환 된 첫 번째 int에 배열 수를 저장하고 그 이후로 포인터 오프셋 operator new[]
을 new[]
반환하는 것입니다. (이것이 사소한 정렬이 깨질 수있는 이유 new[]
입니다.)
있음을 알아 두셔야합니다 operator new[]/operator delete[]
! = new[]/delete[]
.
또한 이것은 C가 할당 한 메모리 크기를 알고있는 방식과 직교합니다 malloc
.
표준화되지 않았습니다. Microsoft 런타임에서 새 연산자는 malloc ()을 사용하고 삭제 연산자는 free ()를 사용합니다. 따라서이 설정에서 귀하의 질문은 다음과 같습니다. free ()는 블록의 크기를 어떻게 알 수 있습니까?
C 런타임과 같은 장면 뒤에 약간의 부기가 있습니다.
이것은 처음에 생각하는 것보다 더 흥미로운 문제입니다. 이 답변은 가능한 한 가지 구현에 관한 것입니다.
첫째, 어떤 수준에서 시스템은 메모리 블록을 '빈'하는 방법을 알아야하지만 기본 malloc / free (new / delete / new [] / delete [] 일반적으로 호출)는 항상 정확히 얼마나 많은 메모리를 기억하지는 않습니다 요청하면 반올림 될 수 있습니다 (예를 들어 4K 이상이면 종종 다음 4K 크기의 블록으로 올림됩니다).
그러므로, 메모리 블록의 크기를 얻을 수 있더라도, 새로운 메모리에 얼마나 많은 값이 있는지를 알려주지는 않습니다. 따라서 우리는 몇 개의 값이 있는지 알려주는 여분의 정수를 저장해야합니다.
예외적으로, 생성중인 타입에 소멸자가 없다면 delete []는 메모리 블록을 비우는 것 외에는 아무것도 할 필요가 없으므로 아무것도 저장할 필요가 없습니다!