2009-06-10 2 views
8

가능한 중복 : How does delete[] "know" the size of the operand array?delete []는 배열의 크기를 어떻게 알 수 있습니까?


How does the standard new operator work in c++?
How does delete[] “know” the size of the operand array?

속는 나는 할당 된 메모리의 크기에서 [] 수치를 삭제하는 방법 궁금합니다. 내가 다음과 같이하면 :

int* table = new int[5]; 
delete[] table; 

나는 테이블의 기억이 자유롭게된다는 것을 알고있다. 하지만 포인터를 다른 테이블에 다시 할당하면 어떻게 될까요?

int* table = new [5]; 
int* table2 = new [9]; 
table = table2; 
delete[] table; 

크기 5 또는 9의 테이블을 무료로 제공합니까? 나는 new []와 delete []가 그들의 크기에 관한 정보를 어떻게 공유하는지에 관심이있다. 아니면 여기에 필수적인 것을 놓치고있을 수도 있습니다.

는 C의
+0

중복되는 (다소간) http://stackoverflow.com/questions/377178/how-does-the-standard-new-operator-work-in-c/377208 –

+3

동의하지 않습니다. 더 구체적입니다. –

+0

부수적으로, 그리고 답변에서 언급했듯이, 이것은 구현 특정 물건입니다. 즉, 컴파일러에서 컴파일러로, 컴파일러 버전에서 컴파일러 버전으로 변경 될 수 있으므로 배열의 크기를 추출하는 방식에 의존해서는 안됩니다. –

답변

10

크기가 9 인 배열을 삭제합니다. 포인터가 가리키는 배열을 삭제합니다.

크기 정보가 저장되는 방법은 지정되지 않으므로 각 컴파일러가 다른 방식으로이를 구현할 수 있지만 일반적인 방법은 배열 앞에 여분의 블록을 할당하는 것입니다. 즉,이 작업을 수행 할 때 :

int* table = new int[5]; 

실제로는 6 개의 정수 배열을 할당하고 첫 번째 요소에 배열 크기를 저장합니다. 그런 다음 두 번째 요소에 대한 포인터를 반환합니다. 그래서 크기를 찾으려면 []을 삭제하면 테이블 [-1]을 읽어야합니다.

일반적인 방법 중 하나이지만 언어 표준에 따라 이어야합니다. 그냥 그것이 일해야합니다.

또 다른 방법은 배열의 주소를 일부 글로벌 해시 테이블의 키로 사용하는 것입니다. 올바른 결과를 산출하는 한 모든 방법이 유효합니다.

+0

감사합니다.이 설명은 제게 많은 의미가 있습니다.나는 여러 답변을 허용 된 대답으로 선택하는 것이 좋았지 만. – Lucas

16

Section 16.14 ++ FAQ 라이트 답변이 이렇게 이 개 인기있는 기술이있다

. 이 두 기술은 모두 상업용 컴파일러에서 으로 사용되며 은 둘 다 절충 적이며 은 적합하지 않습니다. 이러한 기술은 다음과 같습니다

* Over-allocate the array and put n just to the left 
    of the first Fred object. 
* Use an associative array with p as the key and n as the value. 
+1

하나의 컴파일러를 연관 배열로 인용 할 수 있습니까? – curiousguy

+0

@curiousguy FAQ의 링크에 따르면 CFront는 다음을 사용합니다. http://www.parashift.com/c%2B%2B-faq-lite/compiler-dependencies.html#faq-38.8 –

+0

15 년 전 [1991 년 마지막 발표] (http://www.softwarepreservation.org/projects/c_plus_plus/index.html#cfront)와 관련이없는 현대 템플릿이 없었습니다. "_Bjarne Stroustrup 메모,"경고 Cfront 3은 사전 표준이며 사용이나 추가 개발이 바람직하지 않을 수도 있습니다. "_" – curiousguy

0

내 생각 엔 새가 [] 실제로는 것보다 더 많은 데이터를 할당하는 것입니다. 배열에 몇 개의 항목이 있는지를 알려주는 포인터가 반환되기 전에 아마 몇 바이트가있을 것입니다.

4

이 작업은 컴파일러 관련 세부 사항입니다. 그러나 메모리 손상이 없다고 가정하고 delete []를 호출하면 항상 올바른 수의 요소가 삭제됩니다. 이를 달성하는 데는 여러 가지 방법이 있지만 한 가지 간단한 방법은 메모리의 길이를 숨기는 것입니다.

데모 목적으로이 기능을 구현하는 방법은 간단합니다. 코드가 새로운 int [10]를 호출한다고 가정 해보십시오.10 * sizeof (int)를 할당하는 대신 컴파일러는 (10 * sizefo (int)) + sizeof (size_t)를 할당합니다. 그런 다음 처음부터 offset_t 크기의 포인터를 반환합니다. 그 초기 size_t 공간 안에는 숫자 10이 기록됩니다. 이제 delete []를 호출하고 포인터를 전달하면 컴파일러는 size_t 바이트만큼 뒤로 이동하고 삭제할 요소의 수를 찾습니다.

+0

아, 네가 나를 때렸어. 똑같은 예를 올릴거야. – gnud

+0

이것은 할당 된 메모리에 숨기는 예제입니다. "포인터에 숨기는"것이 아닙니다. –

+0

@ 단, 옙이 오타를 수정했습니다. – JaredPar

1

메커니즘은 구현에 따라 다르지만 예제에 포인터를 재 할당하면 "바보"되지 않습니다. 그것은 당신이 말했듯이, 크기 9의 배열을 할당 해제 할 것입니다 (그리고이 경우에는 크기 5의 배열에 아무것도 가리 키지 않기 때문에 메모리 누수가 발생합니다).

2

delete [] 작동 방식은 구현에 따라 다르지만 글로벌 new 연산자는 어떤 식 으로든 할당 된 메모리와 연관됩니다 (대부분의 경우 할당 된 메모리 앞에 추가되거나 조회 테이블에 저장됩니다). 디스크립터는 할당 된 메모리의 실제 크기를 포함합니다.

두 번째 코드 예제에서는 delete []가 9 요소 배열 int를 올바르게 삭제하고 원래 5 요소 배열이 누수됩니다.

0

당신은 시스템 저장소 이와 같은 구조의 테이블의 크기를 상상할 수 :

struct MemoryAllocated 
    { 
    size_t sizeOfMemory; 
    char* yourData; 
    } 

각각이 어떤 메모리를 할당 입력 시스템은 'yourData'에 대한 포인터를 반환합니다. 그리고 각각의 타입이 당신의 메모리가 'free'라면, 시스템은 'sizeOfMemory'를 얻기 위해 포인터를 이동시킵니다. 참고 사항 std :: allocator

0

new []/delete []의 경우 메모리와 관련하여 어떤 일이 발생합니까?/새/삭제의 경우와 비슷합니다 ... 크기 정보는 (더 큰) 할당 된 블록 자체. 배열에서 흥미로운 점은 소멸자를 호출 할 객체의 수를 알기 위해 크기 정보를 사용한다는 것입니다.

관련 문제