[choreonoid-users-ja 00142] Plugin中でViewを動的に削除する方法

植芝 俊夫 t.ueshiba @ aist.go.jp
2014年 11月 19日 (水) 07:56:18 JST


産総研の植芝と申します.最近,choreonoidをビジョンシステムのGUIプラットフォームとして
使わせて頂くようになりました.素晴らしいソフトウェアを公開していただき,ありがとう
ございます.

当方の使用環境は,ubuntu-12.04 または MacOS X 10.9.5(Marvericks) の上で,ソースからコンパイル
したchoreonoid-1.4.0 を動かしています.ユーザからの指示で複数のViewを動的に生成/削除
するPluginを書きたいと思っています.この場合,Viewを生成するためには

	View* view = new View();
	addView(view);

とすれば良いことはわかるのですが,生成したviewを陽に削除するにはどうすれば良いのでしょうか?
試しに

	bool removed = MainWindow::instance()->removeView(view)

としてみましたが,戻り値はtrueになるもののタブからViewが消えません.強引に

	delete view;

とすると,そのときは消えるものの,choreonoid本体を終了したときにsegmentation faultします.
このとき,MacOS X上では

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libCnoidBase.1.4.dylib        	0x0000000105314d44 cnoid::ExtensionManager::PtrHolder<cnoid::View*>::~PtrHolder() + 36
1   libCnoidBase.1.4.dylib        	0x0000000105313e91 cnoid::ExtensionManagerImpl::~ExtensionManagerImpl() + 113
2   libCnoidBase.1.4.dylib        	0x0000000105313d32 cnoid::ExtensionManager::~ExtensionManager() + 34
3   libCnoidMultiviewPlugin.dylib 	0x000000010fc86901 MultiviewPlugin::~MultiviewPlugin() + 65 (MultiviewPlugin.cc:9)
4   libCnoidMultiviewPlugin.dylib 	0x000000010fc7f355 MultiviewPlugin::~MultiviewPlugin() + 21 (MultiviewPlugin.cc:9)
5   libCnoidMultiviewPlugin.dylib 	0x000000010fc7f379 MultiviewPlugin::~MultiviewPlugin() + 25 (MultiviewPlugin.cc:9)
6   libCnoidBase.1.4.dylib        	0x00000001052be7f9 

というようなエラーメッセージが出ますので,スマートポインタ型であるExtensionManager::PtrHolder<View*>が
管理しているviewを勝手にdeleteしたため,スマートポインタのデストラクタが呼ばれた時に2重解放になった
のではないかと推測しています.

安全にViewを削除する方法をご教示いただければ幸いです.どうかよろしくお願いいたします.

ご参考までに,動作チェックのために書いたコードを以下に添付します.メインメニューの”表示”に”New view”と
“Close view”の2項目を追加し,前者を選択すると新たなViewを生成,後者を選択すると直近に生成
したViewを削除する(つもり)のコードです.このコードのままではメニュー操作によってViewを消すことは
できず,”#if 1”を”#if 0”とすると消すことはできるものの,choreonoid終了時にクラッシュします.


===================================

#include <cnoid/Plugin>
#include <cnoid/View>
#include <cnoid/MenuManager>
#include <cnoid/MainWindow>
#include <cnoid/MessageView>
#include <boost/bind.hpp>
#include <stack>

class MultiviewPlugin : public cnoid::Plugin
{
  public:
    typedef cnoid::View	View;
    
  public:
    MultiviewPlugin()	:Plugin("Multiview")	{}
    
    virtual bool
    initialize()
    {
	menuManager().setPath("/View")
		     .addItem("New view")
		    ->sigTriggered()
		     .connect(boost::bind(&MultiviewPlugin::onNew, this));
	menuManager().setPath("/View")
		     .addItem("Close view")
		    ->sigTriggered()
		     .connect(boost::bind(&MultiviewPlugin::onClose, this));
    
	return true;
    }

    void
    onNew()
    {
	View*	view = new View();
	view->setName("My view");
	_views.push(view);
		    
	addView(view);
    }
    
    void
    onClose()
    {
	if (_views.empty())
	    return;
		    
	View*	view = _views.top();
	_views.pop();

#if 1
	using namespace	cnoid;
	
	bool	removed = MainWindow::instance()->removeView(view);	// viewが消えない
	if (removed)
	    MessageView::instance()->putln("MultiviewPlugin: Removed.");
	else
	    MessageView::instance()->putln("MultiviewPlugin: Not Removed.");
	    
	MainWindow::instance()->update();
#else
	delete view;	// viewは消えるが,choreonoid終了時にSEGV
#endif
    }
    
  private:
    std::stack<View*>	_views;
};
    
CNOID_IMPLEMENT_PLUGIN_ENTRY(MultiviewPlugin);

===================================

===================================================================
植芝俊夫  t.ueshiba @ aist.go.jp

産業技術総合研究所
知能システム研究部門 タスクビジョン研究グループ

   Addr.: 〒305-8568 つくば市梅園1-1-1 産総研つくば中央第2
   Phone: 029-861-5959



choreonoid-users-ja メーリングリストの案内