查看: 12243|回复: 58

程序运行时removechild报错

[复制链接]

该用户从未签到

发表于 2009-11-3 20:49:13 | 显示全部楼层 |阅读模式
我给我的程序中定义所有的Group对象都加上了setDataVariance(osg::Object:YNAMIC) 可是还是老报错,怎么办啊?
似乎用了setDataVariance就可以不用updatecallback了啊,可是还报这种错误。

该用户从未签到

发表于 2009-11-4 08:28:21 | 显示全部楼层
???你的问题很难判断,,请提供更多的信息~~~我觉得很大可能是你的程序本身的问题!!setDataVariance和UpdateCallBack是两个不同的机制,,,请仔细阅读《OSG快速入门指南》,,里面有详细的讲解~~~

该用户从未签到

发表于 2009-11-4 08:46:53 | 显示全部楼层
您的报错恐怕是别的问题,请自行排查,或者提供更多的信息

该用户从未签到

 楼主| 发表于 2009-11-4 09:41:56 | 显示全部楼层
查看出错信息,看样子很像是裁剪的时候删除数据,所以出现指针为空的错误。

>        webvrd.dll!std::_Vector_const_iterator<osg::ref_ptr<osg::Node>,std::allocator<osg::ref_ptr<osg::Node> > >:perator++()  行117 + 0x33 字节        C++
        webvrd.dll!std::_Vector_iterator<osg::ref_ptr<osg::Node>,std::allocator<osg::ref_ptr<osg::Node> > >::operator++()  行337        C++
        webvrd.dll!osg::Group::traverse(osg::NodeVisitor & nv={...})  行60 + 0x8 字节        C++
        webvrd.dll!osg::NodeVisitor::traverse(osg::Node & node={...})  行191 + 0x1c 字节        C++
        webvrd.dll!osgUtil::CullVisitor::handle_cull_callbacks_and_traverse(osg::Node & node={...})  行301        C++
        webvrd.dll!osgUtil::CullVisitor::apply(osg::Group & node={...})  行975        C++
        webvrd.dll!osg::Group::accept(osg::NodeVisitor & nv={...})  行38 + 0x41 字节        C++
        webvrd.dll!osg::Group::traverse(osg::NodeVisitor & nv={...})  行62 + 0x25 字节        C++
        webvrd.dll!osg::NodeVisitor::traverse(osg::Node & node={...})  行191 + 0x1c 字节        C++
        webvrd.dll!osgUtil::CullVisitor::handle_cull_callbacks_and_traverse(osg::Node & node={...})  行301        C++
        webvrd.dll!osgUtil::CullVisitor::apply(osg::Group & node={...})  行975        C++
        webvrd.dll!osg::Group::accept(osg::NodeVisitor & nv={...})  行38 + 0x41 字节        C++
        webvrd.dll!osgUtil::SceneView::cullStage(const osg::Matrixd & projection={...}, const osg::Matrixd & modelview={...}, osgUtil::CullVisitor * cullVisitor=0x049cc2a0, osgUtil::StateGraph * rendergraph=0x049cd2e0, osgUtil::RenderStage * renderStage=0x049cbee8, osg::Viewport * viewport=0x049c9278)  行962 + 0x38 字节        C++
        webvrd.dll!osgUtil::SceneView::cull()  行828 + 0x57 字节        C++
        webvrd.dll!osgViewer::Renderer::cull_draw()  行552 + 0xf 字节        C++
        webvrd.dll!osgViewer::Renderer::operator()(osg::GraphicsContext * context=0x049c7b70)  行695 + 0xf 字节        C++
        webvrd.dll!osg::GraphicsContext::runOperations()  行692 + 0x33 字节        C++
        webvrd.dll!osgViewer::ViewerBase::renderingTraversals()  行804        C++
        webvrd.dll!osgViewer::ViewerBase::frame(double simulationTime=1.7976931348623157e+308)  行639 + 0xf 字节        C++
        webvratl.dll!CoreOSG::RenderThread(void * ptr=0x049c6c78)  行410 + 0x1b 字节        C++
        msvcr80d.dll!_callthreadstart()  行293 + 0xf 字节        C
        msvcr80d.dll!_threadstart(void * ptd=0x049c5ff8)  行277        C

该用户从未签到

 楼主| 发表于 2009-11-4 10:26:51 | 显示全部楼层
最后在vector文件:
        _Myt& operator++()
                {        // preincrement
                _SCL_SECURE_VALIDATE(this->_Mycont != NULL);//此处报错
                _SCL_SECURE_VALIDATE_RANGE(_Myptr < ((_Myvec *)(this->_Mycont))->_Mylast);
                ++_Myptr;
                return (*this);
                }

查看this的值,osg:bject中的_datavariance的值还是Dynamic的,但是查看this->_Mycont就成了: _Myfirstiter = CXX0030: 错误: 无法计算表达式的值

我是用的MFC+osg框架,创建线程:
        mThreadHandle = (HANDLE)_beginthread(&CoreOSG::RenderThread, 0, m_coreOSG) ;

该用户从未签到

发表于 2009-11-4 12:05:40 | 显示全部楼层
您发上来的东西恐怕对于排查没有任何意义。

该用户从未签到

 楼主| 发表于 2009-11-4 12:18:49 | 显示全部楼层
那我把出错的函数发上来,如下:
void CoreOSG::cartoonEffectFunc()
{
        if (effectFlag == false)
        {
                storageTree->removeChild(effectGroup.get());
                storageTree->addChild(cartoonEffect.get());
                cartoonEffect->setEnabled(true);
                numOfEffect = CARTOON;


                effectFlag = true;
        } else if (effectFlag == true)
        {
                removeEffect();
                if (numOfEffect != CARTOON)
                {
                        storageTree->removeChild(effectGroup.get());
                        storageTree->addChild(cartoonEffect.get());
                        cartoonEffect->setEnabled(true);
                        numOfEffect = CARTOON;
                        effectFlag = true;


                }

        }
}

其中,storageTree,effectGroup,cartoonEffect都设置为动态了

该用户从未签到

 楼主| 发表于 2009-11-4 12:32:08 | 显示全部楼层
阿ray有空吗,我把整个项目发你给帮我看看可以吗?

该用户从未签到

发表于 2009-11-4 13:10:13 | 显示全部楼层
不要把整个项目发给我。我不明白您为什么要频繁地addChild和removeChild,个人认为只有在增添或去除模型数据的时候才会用到这些;对于各种特效的切换,则有很多方法可以避开这些操作

该用户从未签到

发表于 2009-11-4 14:04:41 | 显示全部楼层
使用线程锁
在添加删除节点线程和frame线程使用线程锁

该用户从未签到

 楼主| 发表于 2009-11-4 14:34:29 | 显示全部楼层
9# array

可以给出例子吗?

该用户从未签到

发表于 2009-11-4 15:03:26 | 显示全部楼层
有很多方法可以组织场景,所以我不会给出什么例子。因为没有一定之规,我的方法和别人的方法都会不同,没有谁对谁错;思维限定死了,就会无所适从——从这一点看来,所谓的“例子”事实上是最害人的东西

该用户从未签到

发表于 2009-11-6 17:55:00 | 显示全部楼层
删除和加载一般都不会有问题,我的一个场景编辑器里,添加和删除节点都是没有问题的。

该用户从未签到

发表于 2009-11-6 17:55:25 | 显示全部楼层
删除和加载一般都不会有问题,我的一个场景编辑器里,添加和删除节点都是没有问题的。

该用户从未签到

 楼主| 发表于 2009-11-6 22:35:50 | 显示全部楼层
这个问题变相的解决了,改到release模式就再也没有出现过了。
可是debug模式下还有问题没,感到很不爽。

该用户从未签到

发表于 2009-11-6 23:17:56 | 显示全部楼层
只能说,很显然是您的代码存在某些隐患

该用户从未签到

 楼主| 发表于 2009-11-7 00:04:36 | 显示全部楼层
打算用10楼的方法试试

该用户从未签到

发表于 2009-11-7 12:33:53 | 显示全部楼层
我想不应该那么复杂,我设计GIS系统的特征量动态编辑功能时,涉及大量的removeChild和addChild操作,都没有遇到过问题。我想您的问题应该出现在别处

该用户从未签到

 楼主| 发表于 2009-11-8 19:01:49 | 显示全部楼层
18# array

osg+mfc或者osg+atl都是给渲染函数单独开了一个线程,所以错误可能在这里。
有一些朋友遇到osg+mfc的解决方案运行很顺畅,但是在关闭的时候报错,估计就是在removechild的时候出错。
这些代码在win32+osg和QT+osg中都没有问题。

该用户从未签到

发表于 2009-11-9 08:41:36 | 显示全部楼层
我个人的建议是GUI的事件机制和OSG场景的操作尽量分离。例如按下按钮之后,只是传递一个命令给OSG的场景对象;然后在下一帧使用更新回调执行这个命令的相应内容——这样可以保证场景操作的绝对安全,我一直是这样做的

该用户从未签到

 楼主| 发表于 2009-11-9 11:07:46 | 显示全部楼层
20# array

我做了简单的实现,但感觉有问题:
class RemoveAllCallback : public osg::NodeCallback
   {
        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {
   (reinterpret_cast<osg::Group*>(node))->removeChildren(0, (reinterpret_cast<osg::Group*>(node))->getNumChildren());
   node->removeUpdateCallback(this);
        }
   };
    调用代码如下:
RemoveAllCallback* removeall=new RemoveAllCallback();
graphicsGroup->setUpdateCallback(removeall);

能指出我的问题在哪吗?

该用户从未签到

发表于 2009-11-9 12:10:10 | 显示全部楼层
这里的reinterpret_cast用得让人感觉不爽而已~~
还有最好不要在回调里就removeUpdateCallback,建议用一个标志量来控制就好了。
除此之外,只要node正确设置了DYNAMIC,应该不会有更多问题

该用户从未签到

 楼主| 发表于 2009-11-9 15:51:14 | 显示全部楼层
removeUpdateCallback写在哪比较合适,我希望她至少执行过一次operator()。

RemoveAllCallback* removeall=new RemoveAllCallback();
graphicsGroup->setUpdateCallback(removeall);
graphicsGroup->removeUpdateCallback(removeall);
不能保证回调被执行过。

该用户从未签到

发表于 2009-11-9 15:54:40 | 显示全部楼层
我已经说过了,用标志量来控制是最简单的;不需要removeUpdateCallback()。比如设置RemoveAllCallback的一个成员变量bool _paused

该用户从未签到

 楼主| 发表于 2009-11-9 15:57:12 | 显示全部楼层
程序中如果有几十个这样的回调,不去释放是不是会影响性能?

该用户从未签到

 楼主| 发表于 2009-11-9 16:16:22 | 显示全部楼层
24# array

这里的reinterpret_cast可以换成别的方式吗?

该用户从未签到

发表于 2009-11-9 16:24:09 | 显示全部楼层
性能没什么好影响的;reinterpret_cast用dynamic_cast更为安全

该用户从未签到

 楼主| 发表于 2009-11-9 17:37:01 | 显示全部楼层
现在实现了一个。
class RemoveAllCallback : public osg::NodeCallback
{
private:
        bool _paused;
        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
public:
        RemoveAllCallback();
        bool get_paused();
        void set_paused(bool val);
};
但是这样就必须把整个命令都放到回调函数中去。
比如:我运行:
        1:removeall->set_paused(false);
        2:removeEffect();
这样不能保证1比2先执行。
必须把2句也放到removeall的operator函数中去。
这样的话,所有包含remove和add操作的函数都要放到回调函数中了,是吗?

该用户从未签到

发表于 2009-11-9 22:54:21 | 显示全部楼层
晕……

第一次执行operator的时候,就在函数内部把默认为false的_paused改成true就好了,然后就相当于停用了回调对象;为啥把这么简单的事情搞复杂了呢?还是说您另有什么打算却一直懒得说明

该用户从未签到

 楼主| 发表于 2009-11-10 09:02:55 | 显示全部楼层
我确实是这样实现的:
RemoveAllCallback::RemoveAllCallback()
{
        _paused=true;
}
void RemoveAllCallback:perator()(osg::Node* node, osg::NodeVisitor* nv)
{
        if(!_paused)
        {
                (dynamic_cast<osg::Group*>(node))->removeChildren(0, (dynamic_cast<osg::Group*>(node))->getNumChildren());
                _paused=true;
        }
        //node->removeUpdateCallback(this);
}

bool RemoveAllCallback::get_paused()
{
        return _paused;
}
void RemoveAllCallback::set_paused(bool val)
{
        _paused=val;
}

我的意思是原有的一个顺序执行的命令,必须全都放到回调函数中,而不可以把其中一部份抽出来放到回调函数中,否则无法保证执行顺序。
有别的方法解决这种函数执行的乱序问题吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表