2016-09-12 4 views
11

다음과 같은 예를 생각해수명이 끝나면 개체 저장소를 암시 적으로 또는 명시 적으로 다시 사용할 수 있습니까?

// create some storage 
alignas(int) char buffer[2 * sizeof(int)]; 

// new object of type int at the storage of buffer, the int pointed 
// to by p begins its lifetime here, buffer's lifetime is over 
int* p = new (buffer) int{42}; 

// some entirely unrelated int 
int j = 17; 

buffer의 끝에서 다른 스토리지, 이미 새로운 int 객체에 의해 사용 p가 가리키는되지 않은 부분에 대한 허용인가를받는 재개한다 자동 저장 기간의 후속 객체에 의해 암시 적으로 재사용됩니까? 즉, 준수 구현에 &j == p+1이 허용 되었습니까?


는 이와 관련, 것 명시 적으로는 다른 저장이 잘 정의 된 행동이 될 재사용? 이다

alignas(int) char buffer[2 * sizeof(int)]; 
int* p = new (buffer) int{42}; 
int* q = new (p+1) int{6}; 

는 모두 intp과 수명에서 여전히 q가 가리키는입니까?

+0

(as-if 규칙을 통해) 허용되지 않지만 완료되지 않았습니다. 스택 포인터를 이동하는 것이 힙에서보다 훨씬 쉽습니다. – OMGtechy

+0

왜 '버퍼'수명이 끝났다고합니까? – Erik

+2

컴파일러가 응용 프로그램에서 'p + 1 '을 사용하지 않는다는 것을 증명할 수 있다면, 그 메모리를 사용했다면 (UB 포인터 비교를하는 것 이외에) 어떻게 알 수 있습니까? – hyde

답변

-2

네, 그렇습니다.

alignas(int) char buffer[2 * sizeof(int)]; 

스택에 8 바이트를 할당하십시오.

int* p = new (buffer) int{42}; 
int* q = new (p+1) int{6}; 

새 연산자는 객체를 구성하기 위해 메모리를 할당하지 않고 대신 버퍼를 사용합니다.

그러나 이러한 개체의 유효 기간은 버퍼 변수의 유효 기간입니다. 버퍼가 파괴 될 때 p & q가 참조 된 메모리가 파괴됩니다.

또한 일반적으로 버퍼가 파괴되기 전에 수동으로 소멸자를 호출한다고 가정합니다.

그래서 "수명이 끝나면 개체 저장소를 암시 적으로 또는 명시 적으로 다시 사용할 수 있습니까?"라는 질문에 대한 대답은 다음과 같습니다. No입니다. 버퍼의 수명이 끝나면 나중에 다른 스택 변수에 사용되기 때문에 메모리를 계속 사용하는 것은 안전하지 않습니다.

P. 나는 당신이 당신의 경우에 이것을 관리하는 것이 더 쉬울 것이라는 것을 이해한다고 믿는다.

int buffer[2]; 
int* p = &buffer[0]; 
int* q = &buffer[1]; 

image

+1

'int *'에'char *'를 지정할 수 없습니다. – Barry

+0

두 번째 부분은 대답하지만 질문의 첫 번째 부분은 무시합니다. – Potatoswatter

+0

OP의 예는 어떻습니까? 변수'j'로? – einpoklum

1

컴파일러는 프로그램의 재사용을 측정 할 수 없다는 것이면 결정할 수 스택의 각 변수에 대한 메모리의 독특한 영역을 사용할 수 있고,하지 않는다 - 예를 들면 두 변수의 주소가 같은지 확인하면 컴파일러가 메모리를 공유하지 않도록 할 수 있습니다.

컴파일러가 별개의 사용을 말할 수 a와 b를 사용 스택 모두, 그들은 주소를 공유 할 수 있다고 가정 예

int a; 
// do some stuff with a. 

int b; 
// do some stuff with b. 

.스택의 항목이 생성

이 예에서는 간단한 명령

sub stackPointer, #AmountOfSpaceNeeded 

이며 공간은 할당의 속도에 영향을 미치지 않는다.

힙에 항목을 만들려면 사용되지 않은 메모리 영역을 찾거나 새로운 주소 공간을 "매핑"해야하며 힙 사용에 대한 지침 (프레임 포인터가 포함 된 두 가지)의 비용이 여러 번 걸립니다. .

또한 개체의 사용 가능한 스페어 메모리 양에 대한 불일치가있는 메모리 검사기에 오탐 (false-positives)을 만들 수 있습니다.

그래서 모든 기능은 힙을 사용하지 않습니다

  1. 로 스택에 저장을 저장, 힙의 위치를 ​​사용의 최적화에 작은 값이 있습니다 사용하여 저장 시간이 없습니다
  2. 그냥 힙
  3. 힙 뒤에있는 코드 메커니즘은 측정을 수행 할 수 있습니다 (버퍼 오버런 감지). 컴파일러가 as-if 규칙을 위반하게됩니다.
  4. 공간이 사용되지 않았 음을 결정할뿐만 아니라 컴파일러는 함수/코드 블록이 완료되기 전에 힙 개체가 파괴 될 수 있으므로 메모리의 수명이 올바른지 확인해야합니다.