2014-11-05 3 views
2

int을 가리키는 두 개의 shared_ptr이 있습니다. 즉, 을 호출하면 동일한 주소가 반환됩니다. 그러나 use_count()을 호출하면 1가 반환됩니다. 이들의 마지막이 범위를 벗어나하면, 이중 무료 런타임 오류가 발생, 이미 다른 하나에 의해 해제 된 메모리를 확보하려고 :std :: shared_ptr의 use_count가 증가하는 모든 방법은 무엇입니까?

같은 일이 명시 적으로 선언 원시 포인터로이 변형에서 발생

#include <memory> 
#include <iostream> 
using namespace std; 

int main() { 
    shared_ptr<int> sp1(make_shared<int>(7)); 
    shared_ptr<int> sp2(&(*sp1)); 
    cout << sp1.use_count() << endl; // 1 
    cout << sp2.use_count() << endl; // 1 
    cout << sp1.get() << endl;  // same address 
    cout << sp2.get() << endl;  // same address 
} 
//^Double free runtime error at closing brace. 
:

int main() { 
    int *raw_ptr = new int(8); 
    shared_ptr<int> sp3(raw_ptr); 
    shared_ptr<int> sp4(raw_ptr); 
    cout << sp3.use_count() << endl; // 1 
    cout << sp4.use_count() << endl; // 1 
    cout << sp3.get() << endl;  // same address 
    cout << sp4.get() << endl;  // same address 
} 
//^Double free runtime error at closing brace. 

이유는 무엇입니까 같은 일에 모두 shared_ptr의 포인트 경우 use_count() 복귀 1 (그러나 2)? use_count()1을 반환하면 int을 두 번 해방하려는 시도가 있었던 이유는 무엇입니까? 나는 shared_ptr이 형제와 동일한 주소 인 shared_ptr을 가리키는 경우에만 use_count을 하나씩 증가시킬 것이라고 생각했습니다.

원시 포인터로의 건설 '첫 shared_ptr 만 증가의 use_count'는 std::shared_ptr (또는 원시 포인터에 할당하는 경우 기본적으로 구성)의 임의에 의한 추가 shared_ptr의 '복사 건설 또는 지정하여 다음과 사전 shared_ptr s? 그렇다면 다른 모든 증가 방법은 무엇입니까?

+1

대신'shared_ptr sp4 = sp3;'를 사용해보십시오. 공유 포인터 객체 자체를 복사해야합니다. 동일한 원시 포인터로 새로운 공유 포인터를 만드는 것은 이제 객체의 독점적 소유권을 갖고 있다고 생각하는 두 개의 공유 포인터를 갖게됨을 의미합니다. 대신에'shared_ptr sp3 (new int (8));'을 쓰면 더 쉽습니다. - 프로그램에서 실수 포인터를 실수로 사용하는 것을 피하기 위해 원시 포인터를 보이지 않게하십시오. – cdhowie

+1

사실, C++ 구현이'int '와'shared_ptr' 제어 블록 모두를위한 공간을 단일 메모리 할당으로 할당 할 수 있기 때문에'auto sp3 = std :: make_shared (8);'이 더 좋다. (이 표준은이 최적화를 필요로하지 않지만 그것을 허용합니다.)'shared_ptr (new int (8)) '을 사용하면이 최적화는 불가능합니다.) – cdhowie

+0

@cdhowie, 좋은 지적. 내 의견은 여기에 다른 사람들이'shared_ptr sp3 (new int (8)); shared_ptr sp4 (새로운 int (8));','sp3'와'sp4'는 같은 값을 가진 다른'int's (다른 주소에서)를 가리 킵니다. – CodeBricks

답변

6

shared_ptr에 포인터를 지정하면 해당 공유 포인터가 해당 포인터의 소유권을 갖습니다. delete에 더 이상 허용되지 않으며 다른 shared_ptr 또는 이와 비슷한 것으로 전달됩니다. 새로운 shared_ptr이 이미 포인터 또는 그와 비슷한 것을 소유하고있는 또 다른 shared_ptr이 있는지를 확인하기위한 글로벌 검색 테이블이 없습니다.

다른 방법으로는 두 번째 shared_ptrshared_ptr (사용 횟수가 증가 함)을 복사하는 대신 동일한 포인터를 전달하여 만들어 졌을 때 이중 자유 오류가 발생했습니다. 나중에 정의되지 않은 동작을 관찰 할 수 없다는 사실은 실제로 발생하는 위치를 변경하지 않습니다.

+0

다른'shared_ptr'의 복사 생성 및 할당이'use_count'를 늘리는 * 유일한 * 방법입니까? – CodeBricks

+1

@ CodeBricks 예.그렇지 않으면 raw 포인터에서 새로운 인스턴스를 생성 할 때 참조 카운트 객체를 찾을 수 있고 다중 스레드 프로그램에서 전역 테이블과의 동기화가 필요하도록 원시 포인터의 전역 테이블이 있어야합니다. 그것은 악몽 일 것입니다. – cdhowie

+0

@codeBricks : 정의되지 않은 동작을 트리거하지 않는 유일한 방법입니다. ('shared_ptr'을 사용하지 못하게하는 많은 멤버 함수가 있는데, 이것에 변화가있을 수 있습니다. 모든 것에 대해 완전히 긍정적이지는 않지만 다른 멤버는 복사 생성이나 복사 할당과 같은 방식으로 동작합니다) –

1

shared_ptr의 복사 생성자를 사용하여 두 번째 공유 포인터를 올바르게 구성해야합니다.

+0

이제 이유를 설명한 다음 할 일을 말한 것뿐 아니라 ... – Deduplicator

관련 문제