delete []는 피연산자 배열의 크기를 어떻게 "알고"있습니까?


250
Foo* set = new Foo[100];
// ...
delete [] set;

배열의 경계를에 전달하지 않습니다 delete[]. 그러나 그 정보는 어디에 저장되어 있습니까? 표준화 되었습니까?


sourceforge.net/projects/fastmm 은 오픈 소스이며 메모리 관리자를 대체합니다. 여기에서 메모리 관리의 작동 방식과 메모리 할당 및 삭제를위한 정보의 출처를 확인할 수 있습니다.

1
FastMM은 Delphi / C ++ Builder 컴파일러에만 해당되며 C ++ 용 범용 메모리 관리자는 아닙니다. 심지어 C ++로 작성되지 않았습니다.
— Remy Lebeau

답변:


181

힙에 메모리를 할당하면 할당자는 할당 한 메모리 양을 추적합니다. 이것은 일반적으로 할당 된 메모리 직전에 "헤드"세그먼트에 저장됩니다. 그렇게하면 메모리를 비울 때 할당 해제자는 메모리를 얼마나 비울 수 있는지 정확히 알 수 있습니다.


4
이것은 C ++의 배열 할당에만 적용됩니다. 다른 모든 할당은 유형의 크기에 의존합니다. 일부 라이브러리는 일반적으로 디버깅 모드에서만 모든 할당 크기를 저장합니다.
— Zan Lynx

97
프로그래머가이 정보를 사용할 수없는 이유는 전혀 없습니다. 함수에 대한 포인터를 전달하고 해제 할 수는 있지만 동일한 함수에서 크기를 직접 얻으려면 추가 매개 변수를 전달해야합니다. 그게 말이 되나요?
— Mark Ruzon 2016 년

26
@Mark, 이론적으로 할당자가 할당 된 블록의 크기 ( 요청 된 블록 의 크기와 다를 수 있음) 를 항상 저장할 수 있기 때문에 적은 양의 의미 가 있습니다 . 특정 할당 자 디자인은 자체 목적으로이 정보가 필요할 수도 있고, 유형 정보를 사용하여 배열이 아닌 힙 할당의 크기 등을 추적 할만큼 정교하지 않을 수도 있습니다. 할당 자에게 요청 된 크기를 저장하도록 강요하기 배열 크기를 직접 전달해야합니다.) 작은 문제 일 수 있지만 할당 자 디자인에 성능에 영향을 줄 수 있습니다.
— Doug McClean

33
죄송하지만이 답변은 요점을 놓칩니다. QuantumPete가 설명한 것은 기본적으로 " free할당 할 메모리 양을 알고있는 방법"입니다. 예, 메모리 블록 크기는 "어딘가"에 의해 malloc(일반적으로 블록 자체에) 저장되므로 free알 수 있습니다. 그러나 new[]/ delete[]는 다른 이야기입니다. 후자는 기본적으로 malloc/ 위에서 작동합니다 free. new[]또한 메모리 블록에 생성 된 요소 수 (와 독립적으로 malloc)를 저장하므로 나중에 delete[]해당 숫자를 검색하고 사용하여 적절한 수의 소멸자를 호출 할 수 있습니다.
— AnT

26
즉, 물리적으로 두 개의 카운터가 블록에 저장됩니다 (블록 크기 (by malloc) 및 요소 개수 (by new[])). 일반적으로 메모리 블록의 크기가 요청 된 크기의 배열에 실제로 필요한 것보다 클 수 있기 때문에 전자는 후자를 계산하는 데 사용할 수 없습니다. 또한 배열 요소 카운터는 사소한 소멸자가없는 유형에만 필요합니다. 사소한 소멸자가있는 유형의 경우 카운터는에 의해 저장 new[]되지 않으며 물론에 의해 검색되지도 않습니다 delete[].
— AnT

23

컴파일러의 접근법 중 하나는 조금 더 많은 메모리를 할당하고 헤드 요소에 요소 수를 저장하는 것입니다.

수행 방법 예 :

여기

int* i = new int[4];

컴파일러는 sizeof(int)*5바이트 를 할당 합니다.

int *temp = malloc(sizeof(int)*5)

첫 sizeof(int)바이트 에 "4"를 저장 합니다

*temp = 4;

그리고 설정 i

i = temp + 1;

따라서 i5가 아닌 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)

9

정보는 표준화되지 않았습니다. 그러나이 정보를 다루는 플랫폼에서 첫 번째 요소 직전에 메모리에 저장됩니다. 따라서 이론적으로 액세스하여 검사 할 수 있지만 그만한 가치는 없습니다.

또한 delete의 배열 버전이 적절한 양의 메모리를 비워야하는 것으로 알고 적절한 소멸자 수를 호출해야한다는 것을 알기 때문에 new []로 메모리를 할당 할 때 delete []를 사용해야하는 이유도 있습니다 객체를 위해.


5

기본적으로 메모리에 다음과 같이 배열됩니다.

[정보] [요청한 ...]

여기서 info는 할당 된 메모리 양을 저장하기 위해 컴파일러에서 사용하는 구조입니다.

이것은 구현에 따라 다릅니다.


4

이것은 사양에있는 것이 아니며 구현에 따라 다릅니다.


3

C ++ 표준에서 컴파일러에 따라 정의됩니다. 이것은 컴파일러의 마술을 의미합니다. 하나 이상의 주요 플랫폼에서 사소한 정렬 제한으로 인해 중단 될 수 있습니다.

에 의해 delete[]반환 된 포인터에 대해서만 정의되며 new[],에 의해 반환 된 포인터와 같지 않을 수 있음을 인식함으로써 가능한 구현에 대해 생각할 수 있습니다 operator new[]. 와일드에서 한 구현은에서 반환 된 첫 번째 int에 배열 수를 저장하고 그 이후로 포인터 오프셋 operator new[]을 new[]반환하는 것입니다. (이것이 사소한 정렬이 깨질 수있는 이유 new[]입니다.)

있음을 알아 두셔야합니다 operator new[]/operator delete[]! = new[]/delete[].

또한 이것은 C가 할당 한 메모리 크기를 알고있는 방식과 직교합니다 malloc.


2

'삭제'할 배열은 'new'연산자를 한 번만 사용하여 만들어야했기 때문입니다. 'new'작업은 해당 정보를 힙에 넣어야합니다. 그렇지 않으면, 새로운 추가 사용은 힙이 끝나는 위치를 어떻게 알 수 있습니까?


0

표준화되지 않았습니다. Microsoft 런타임에서 새 연산자는 malloc ()을 사용하고 삭제 연산자는 free ()를 사용합니다. 따라서이 설정에서 귀하의 질문은 다음과 같습니다. free ()는 블록의 크기를 어떻게 알 수 있습니까?

C 런타임과 같은 장면 뒤에 약간의 부기가 있습니다.


5
사실이 아니다. free를 호출하기 전에 delete []가 먼저 소멸자를 호출해야합니다. 이를 위해서는 총 할당 크기가 충분하지 않습니다. 실제로 new []와 delete []는 VC ++에서 일반 및 파괴 된 유형에 대해 다르게 작동합니다.
— Suma

0

이것은 처음에 생각하는 것보다 더 흥미로운 문제입니다. 이 답변은 가능한 한 가지 구현에 관한 것입니다.

첫째, 어떤 수준에서 시스템은 메모리 블록을 '빈'하는 방법을 알아야하지만 기본 malloc / free (new / delete / new [] / delete [] 일반적으로 호출)는 항상 정확히 얼마나 많은 메모리를 기억하지는 않습니다 요청하면 반올림 될 수 있습니다 (예를 들어 4K 이상이면 종종 다음 4K 크기의 블록으로 올림됩니다).

그러므로, 메모리 블록의 크기를 얻을 수 있더라도, 새로운 메모리에 얼마나 많은 값이 있는지를 알려주지는 않습니다. 따라서 우리는 몇 개의 값이 있는지 알려주는 여분의 정수를 저장해야합니다.

예외적으로, 생성중인 타입에 소멸자가 없다면 delete []는 메모리 블록을 비우는 것 외에는 아무것도 할 필요가 없으므로 아무것도 저장할 필요가 없습니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.