2010-04-02 5 views
4

이 코드를 작성했습니다.
생성자가 정상적으로 작동하지만 소멸자에서 "Windows가 중단 점을 트리거했습니다."라는 메시지가 나타납니다. 이 문제를 어떻게 해결해야합니까?소멸자에서 삭제 문제

template class CyclicalArray { 
private: 
    T* mem_ptr; 
public: 
    CyclicalArray(size_t capacity, const T& default_value) { 
    this->default_value = default_value; 
    this->capacity = capacity; 
    head_index = 0; 
    mem_ptr = ::new T[capacity]; //memory allocating 
    for(T* p = mem_ptr; p < mem_ptr + capacity * sizeof(T); p += sizeof(T)) { 
     ::new (p) T (default_value); //initialization 
    } 
} 
~CyclicalArray() { 
    for(T* p = mem_ptr + sizeof(T); p < mem_ptr + capacity * sizeof(T); p += sizeof(T)) { 
     p->~T(); 
    } 
    delete[] mem_ptr; 
} 

답변

8

새로 배치를 수행하려면 원시 메모리에서 수행해야합니다. 같은 뭔가 :

template class CyclicalArray { 
private: 
    T* mem_ptr; 
public: 
    CyclicalArray(size_t capacity, const T& default_value) { 
    this->default_value = default_value; 
    this->capacity = capacity; 
    head_index = 0; 
    mem_ptr = reinterpret_cast<T*>(::new char[capacity * sizeof(T)]); //memory allocating 
    for(T* p = mem_ptr; p < mem_ptr + capacity; ++p) { 
     ::new (p) T (default_value); //initialization 
    } 
} 
~CyclicalArray() { 
    // this 
    for(T* p = mem_ptr + capacity; p != mem_ptr; --p) { 
     (p-1)->~T(); 
    } 
    delete[] reinterpret_cast<char*>(mem_ptr); 
} 

그렇지 않으면 당신은 같은 객체 메모리 (안 좋은 것)에 두 번 T의 소멸자를 호출 할 수 있습니다.

또한 p 포인터의 유형이 T*이므로 간단한 증분/감소를 수행 할 수 있습니다. 컴파일러는 sizeof(T) 문제를 일반적인 포인터 연산 방식으로 처리합니다.

마지막으로 엄밀히 말하면 배열 요소를 내림차순으로 (건설의 반대) 파괴해야합니다.

이 버그가 대부분 또는 모든 버그를 포착하기를 바랍니다.

std :: vector와 같은 것을 저장소로 사용하는 것이 좋습니다. std::vector<>을 사용하는 예제는 다음과 같습니다 (몇 가지 다른 구문 수정 포함). 클래스 정말 default_value 또는 head_index의 사본을 필요가 있는지 확실하지 않습니다 - 당신이 다른 방법으로 사용할 계획 가정에서 그들을 왼쪽 :

#include <vector> 

template <typename T> 
class CyclicalArray { 
private: 
    std::vector<T> backing_store; 
    T default_value; 
    size_t head_index; 

public: 
    CyclicalArray(size_t capacity, const T& def_val) : 
     backing_store(capacity, def_val), 
     default_value(def_val), 
     head_index(0) { 
    } 

    ~CyclicalArray() {} 
}; 

주 얼마나 간단 생성자와 소멸자 첫 번째 클래스의 모든 복잡성은 std:vector에 의해 관리되므로

7

아마 mem_ptr 배열의 끝을 넘을 것입니다. C 및 C++에서 포인터 산술은 바이트가 아니라 관련된 유형의 단위입니다. 예를 들어 int *a; 인 경우 a이 0x100이고 sizeof(int) == 4 인 경우 a + 1은 0x104입니다.

따라서 제곱의 크기에 따라 p을 증가시킵니다.이 숫자에 1을 더하면 sizeof(T) 바이트가 이동하므로 sizeof(T)을 추가하면 너무 많이 증가하므로 제곱의 크기만큼 증가시킵니다.

delete []이 사용자를 대신하여 처리하므로 배열에서 개별 소멸자를 호출 할 필요가 없습니다.

1

new 대신 글로벌 기능 operator new을 사용하십시오. 메모리를 할당하지만 생성자는 호출하지 않습니다. 삭제에 대한 동일 : 새로운 표현과 삭제 표현을 사용하고 있기 때문에 당신은 두 번 생성자와 소멸자를 호출

template class CyclicalArray { 
private: 
    T* mem_ptr; 
public: 
    CyclicalArray(size_t capacity, const T& default_value) { 
    this->default_value = default_value; 
    this->capacity = capacity; 
    head_index = 0; 
    mem_ptr = static_cast<T*>(::operator new[] (sizeof(T)*capacity)); //memory allocating 
    for(T* p = mem_ptr; p < mem_ptr + capacity; p ++) { 
     ::new (p) T (default_value); //initialization 
    } 
} 
~CyclicalArray() { 
    for(T* p = mem_ptr; p < mem_ptr + capacity; p ++) { 
     p->~T(); 
    } 
    ::operator delete[](static_cast<void*>(mem_ptr)); 
} 
+0

내가 실수하지 않는다면,'std :: allocator '와'allocate (capacity)','construct (p, default_value)','destroy (p)'와'deallocate (mem_ptr, capacity)'? – UncleBens

1

:

// This allocates and calls constructor 
mem_ptr = ::new T[size]; 

// This calls the destructor and deallocates the memory 
delete[] mem_ptr; 

그냥 원시 메모리를 할당 할 경우, 연산자 new를 명시 적으로 호출 할 수 있습니다.

// This simply allocates raw memory 
mem_ptr = ::operator new(sizeof(T) * size); 

// And this simply deallocates memory 
::operator delete(mem_ptr); 
1

게재 위치를 새로 사용하는 이유는 무엇입니까?그 코드는 기본적으로이 귀결 :

template <class T> 
class CyclicalArray { 
private: 
    T* mem_ptr; 
    size_t capacity; 
    T default_value; 
    size_t head_index; 
public: 
    CyclicalArray(size_t capacity, const T& default_value) : capacity(capacity), default_value(default_value), head_index(0) { 
     mem_ptr = new T[capacity](default_value); //memory allocating and construction 
    } 

    ~CyclicalArray() { 
     delete[] mem_ptr; 
    } 
}; 

편집 : 새로운 배치를 사용하고자 할 경우, 루프는 다음과 같아야합니다

for(T* p = mem_ptr; p != mem_ptr + capacity; ++p) { 

sizeof(T)에 의해 일을 확장 할 필요, C/C++로 끝난다.

관련 문제