2017-04-24 2 views
0
Foo* foo1 = static_cast<Foo*>(alloca(sizeof(Foo) * numTargets)); 
new (foo1) Foo(); // Statement 1: Calls constructor Foo() 

Foo** foo2 = static_cast<Foo**>(alloca(sizeof(Foo*) * numTargets)); 
new (foo2) Foo*(); // Statement 2: Doesn't calls constructor Foo() 

현재 프로젝트에서 문장 1 & 2가 없습니다.alloca에 의해 반환 된 포인터의 인덱스 기반 액세스와 "placement new"의 효과

성명 1을 가지고 있지 않으면 foo1[i]에 값을 채우려는 시도가있을 때 (버그) 인 경우 이 충돌합니다. 나는 진술 # 1을 도입함으로써 그것을 고쳤다. 그러나 나는 몇 가지에 대해 확실하지 않다 :

  1. 나는 new (foo1) Foo[numTargets ]; 대신
  2. new (foo1) Foo();의 사용해야 나는 미래의 버그에 대해 safegaurding에 대한 문 # 2를 도입해야 하는가? 진술 # 2는 실제로 어떤 영향을 미칩니 까?
  3. 성명서 # 1이 충돌을 방지하는 데 어떻게 도움이됩니까?
  4. 두 경우 모두 메모리 누수가 있습니까? 두 경우 모두 명시 적으로 소멸자를 호출해야합니까?
+0

관련성이 매우 높습니다. http://stackoverflow.com/questions/8720425/array-placement-new-requires-unspecified-overhead-in-the-buffer – StoryTeller

답변

2

나는 new (foo1) Foo[numTargets ]; 대신 배열 배치 새로운 배열에 대한 세부 정보를 저장하기 위해 할당에 추가 메모리를 필요로 번호

new (foo1) Foo();의 사용해야합니다. C++ 표준은 추가 메모리의 양이 지정되지 않았다고 말하면 C++ 컴파일러 및/또는 표준 라이브러리 구현에 달려 있음을 의미합니다.

당신이해야하는 대신 배열 및 배치 새로운 각 개체를 통해 루프 :

for (size_t i = 0; i < numTargets; ++i) { 
    new (foo1 + i) Foo(); 
} 

내가 앞으로 버그에 대해 safegaurding에 대한 문 # 2를 도입해야 하는가? 진술 # 2는 실제로 어떤 영향을 미칩니 까?

이 모든 설정은 foo2[0]nullptr과 동일하게 설정됩니다.

크래시 방지에 도움이되는 진술은 무엇입니까?

아직 생성되지 않은 개체를 사용하는 것은 정의되지 않은 동작입니다. 크래시는 가능한 한 결과이지만 가리키는 대상이 작성되기 전에 어떤 방식 으로든 foo1을 역 참조하면 작동 할 수 있습니다.

두 경우 모두 메모리 누수가 있습니까? 두 경우 모두 명시 적으로 소멸자를 호출해야합니까?

효과적으로 포인터 배열을 가지고 있다는 점을 제외하면 두 번째 메모리 누수가 없습니다. 이 배열에 요소를 할당하고 그 요소가 delete이 아닌 경우이 배열이 할당을 소유하는지 여부에 따라 할당을 누출시킬 수 있습니다.

첫 번째 경우에는 명시 적으로 소멸자를 호출해야합니다. 따라서 객체가 동적으로 할당 할 수있는 메모리가 무엇이든간에 메모리 누수가 발생하지 않도록해야합니다.

for (size_t i = 0; i < numTargets; ++i) { 
    foo1[i].~Foo(); 
} 

솔직히, 당신은 여기 std::vector을 개시 훨씬 더 좋을 것이다.