2010-07-09 9 views
3

블렌더와 같은 기능을 갖춘 Qt 기반 앱을 작성하고 있습니다.
shared_from_this이 예외를 throw합니다

GUI + 플러그인 시스템 및 플러그인 인 '프레임 워크'로 구성됩니다. 플러그인은 기본적으로 생성되고 표시 될 수있는 객체 (예 : 구, 상자 등)가있는 Qt dll입니다. 그 모든 객체는, 한 번 생성) (

는 내가 원하는 것은 shared_from_this을 사용하는 것입니다 (그래서 실제로 컨테이너는 거의 vector<shared_ptr<INode>> 같다) 그들에게 shared_ptr의의의를 보유하고 컨테이너 구조의 어떤 종류의 프레임 워크에 저장됩니다 플러그인 중 하나의 내부 기능. 예. 다음은 샘플 플러그인 (명확성을 위해 변경 코드)입니다 :

class INode: public QObject, public boost::enable_shared_from_this<INode> 

, 컨테이너에 저장된 모든 기본 클래스 : INode

class Q_DECL_IMPORT SphereNode: public INode, public Sphere 

. 그래서 문제는이 함수는 다음과 같습니다.

void SphereNode::update() 
{ 
foo(shared_from_this()); 
} 

boost::bad_weak_ptr 예외를 throw합니다.

이 SphereNode가 생성되는 방법을 노트의 커플 (팩토리 클래스)

boost::shared_ptr<INode> NodeFactory::createNode(const QString& type, QString tag) 
{ 
... 
QPluginLoader loader(filesPlugin_[i]); 
boost::shared_ptr<QObject> plugin(loader.instance()); 
boost::shared_ptr<INode> iNodePlugin = boost::shared_dynamic_cast<INode>(plugin); 
return iNodePlugin; 
} 

어떤 아이디어가?

+0

참고 : QObject에서 공유 포인터를 사용하지 않습니다. 클래스의 사용자가 부모를 설정하면 공유 포인터와 부모가 삭제 될 때 객체가 삭제되므로 이중 삭제 문제가 발생합니다. 그들 자신. –

+0

@ 프랭크 : 당신은 확실합니까? 나는'QObject'가 삭제 될 때 그들의 부모로부터 참조를 해방시킬만큼 충분히 똑똑하다고 생각했다. – ereOn

+0

ereOn : 예, 공유 포인터가 먼저 오면 부모가 알아 차릴 것입니다. 그러나 부모가 자식을 먼저 삭제하면 공유 포인터는 객체 -> 이중 삭제를 삭제합니다. –

답변

2

은 아마도이 라인 : 교체해야합니다

boost::shared_ptr<INode> iNodePlugin = boost::shared_dynamic_cast<INode>(plugin); 

:

boost::shared_ptr<INode> iNodePlugin = dynamic_cast<INode*>(loader.instance())->shared_from_this(); 

어쩌면 함께 할 수있는 뭔가가 : 여기

boost::shared_ptr<QObject> plugin(loader.instance()); 

plugin을 소유주의 반환 된 인스턴스. 그러나 Qt documentation은 파괴시 인스턴스가 자동으로 QPluginLoader에 의해 해제된다는 내용입니다.

그러나 이것은 보통 boost::bad_weak_ptr 예외보다 segfault (정의되지 않은 동작)를 유발합니다.

이를 방지하려면, 당신은 참조 카운터가


0 당신이 생성자 또는 소멸자 (직접 또는 간접적으로) 중 하나에서 shared_from_this()를 호출 reachs 때 아무것도하지 않는 것 null_deleter를 지정할 수 있습니다 ?

그렇다면 문제가 있습니다.

생성자에있을 때 개체가 아직 완전히 생성되지 않았으므로 shared_ptr이 잘못되었습니다.

이 문제가 발생하지 않도록하려면 개체가 성공적으로 생성되었을 때 shared_ptr을 (이미 가지고있는) 팩터 리 메서드로 개체에 가져올 수 있습니다.

+0

아니요. 먼저 NodeFactory :: createNode를 사용하여 SphereNode를 만든 다음 컨테이너에 넣은 다음 SphereNode :: update()를 호출합니다. 그래서 생성자는 shared_from_this()의 실제 호출 전에 오래 전에 호출되었습니다. – Mikhail

+0

@Mikhail : 내 대답에 몇 가지 요소를 추가했습니다. 비록 그것이 도움이되는지 확실하지 않습니다. 그것에 대해 계속 생각할 것입니다. – ereOn

+0

감사합니다. 소유권이있는 것으로 생각합니다. 게다가 내가 만든 첫 번째 shared_ptr은 shared_ptr 입니다. QObject는 boost :: enable_shared_from_this에서 상속받지 않았습니까? enable_shared_from_this 내부의 weak_ptr이 null 인 이유가 될 수 있습니까? – Mikhail

관련 문제