2011-12-29 4 views
1

이 코드의 문제점 및 해결 방법은 무엇입니까?이 명시 적 소멸자가 공유 ptr에서 메모리 손상을 일으키는 이유는 무엇입니까?

#include <iostream> 
#include <boost/shared_ptr.hpp> 
#include <vector> 

struct CTest 
{ 
    CTest() 
    { std::cout << "ctor CTest" <<std::endl; } 

    ~CTest() 
    { std::cout << "dtor CTest" <<std::endl; } 
}; 

struct CSlot 
{ 
    CSlot() : m_test(new CTest()), m_num(123) 
    { } 

    ~CSlot() 
    { 
     // m_test.reset(); // this line fixed the code but I don't know why 
     m_num = -1; 
    } 

    boost::shared_ptr<CTest> m_test; 
    int m_num; 
}; 

int main() 
{ 
    std::vector<CSlot> testVector(1); 

    std::cout << "1" << std::endl; 
    new (&testVector[0]) CSlot(); 

    // clear slot 
    testVector[0].~CSlot(); 
    std::cout << "2" << std::endl; 
} 

이 코드가 작동 모양, 및 인쇄 :

ctor CTest 
1 
ctor CTest 
dtor CTest 
2 

하지만 때로는 프로그램 충돌 및 Valgrind의 항상 말한다 :

==13372== Invalid read of size 4 
==13372== at 0x400D8F: boost::detail::atomic_exchange_and_add(int*, int) 
... 

내가 m_test.reset으로이 문제를 해결할 수 있습니다() 라인,하지만 더 정확한 해결책이라고 생각합니다 ...

답변

6

당신이하고있는 일이 결코 nse. 객체를 만들고 나서 같은 주소에 객체를 만듭니다.

그런 다음 해당 주소의 개체를 파괴하고 있습니다. 그러면 그 개체를 다시 파괴합니다.

어떻게 작동할까요?

당신은 CSlot 개체의 벡터를 물었습니다. 그래서 그것이 여러분에게 주어졌습니다. 크기가 1이되도록 요청 했으므로 완전히 구성되어 작업 준비가 된 CSlot 개체가 포함되어 있습니다. 따라서 위에 CSlot 개체를 구성하는 것은 의미가 없습니다.

새로운 배치를 사용하고 소멸자를 직접 호출하려면 빈 char 버퍼로 가져와야합니다.

+0

기본 값으로 슬롯을 만들고 나중에 새로운 배치로 초기화하고 때로는 명시 적 소멸자로 재설정합니다. 아마도 shared_ptr에 대한 다른 생성자가 필요합니다. –

+0

"새 배치를 사용하고 소멸자를 호출하려면 직접 빈 빈 버퍼로 처리해야합니다. " 정확히. 제대로 정렬 된 원시 메모리를 사용해야합니다. 그러나 char 버퍼가 제대로 정렬되었는지 확인하는 것이 좋습니다. –

+0

@SergeDundich : 나는 그것을 단순하게 유지하려고 노력하고 있었고 char []가 이것을하기위한 가장 일반적인 방법이었다. ;) – jalf