查看: 2204|回复: 11

智能指针怎么这么难用啊!

[复制链接]

该用户从未签到

发表于 2009-5-20 10:50:43 | 显示全部楼层 |阅读模式
自己在回调中应用智能指针动态的添加删除场景节点来实现内存的释放,所有需要添加删除的节点都被定义为智能指针,需要添加的节点被加到g_addNode组节点中,需要删除的节点被加入到g_delNode组节点中,g_addNode与g_delNode是随视点不断更新的,每次回调中将节点从根节点中添加或删除,但每次智能指针在执行unref()时老是出错。请高手帮忙给看看,谢谢了!!!以下是回调中的代码:
#pragma once
#include<osg/nodeCallBack>
#include<osg/Group>

#include "stdafx.h"
#include "MFC_OSG_MDI.h"
#include "MFC_OSG_MDIDoc.h"
#include "MFC_OSG_MDIView.h"
extern osg::Group *g_addNode;
extern osg::Group *g_delNode;
extern bool  b_IsHugeDataPageOn;
extern CMFC_OSG_MDIView *tepview;
class CSceneUpdate :
        public osg::NodeCallback
{
public:
        CSceneUpdate(void);
        ~CSceneUpdate(void);
public:
          virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
   {
           if(b_IsHugeDataPageOn==true)
         {
           long num = 0;
          // osg::ref_ptr<osg::Node> ptNode;
          //osg::Node *ptNode=NULL;
           osg::Group *ptGp = NULL;   
           ptGp = dynamic_cast<osg::Group *>(node);
            if(g_addNode->getNumChildren()>=1)
         {
           num = g_addNode->getNumChildren();
           osg::ref_ptr<osg::Node> ptNode;
           {
                   for(int  i = 0;i<num;i++)
                   {
                           ptNode= g_addNode->getChild(i);
                           if(ptGp!=NULL&&tepview->m_pNodes!=NULL)
                           {
                                   ptGp->addChild(ptNode.get());
                                   tepview->m_pNodes->addChild(ptNode.get());
                           }
                   }
                   num = g_addNode->getNumChildren();
                   for(int i = num-1;i>=0;i--)
                   {
                          ptNode = g_addNode->getChild(i);
                          if(ptNode.valid())
                          {
                                  g_addNode->removeChild(ptNode.get());
                          }   
                   }

           }
          }
           if(g_delNode->getNumChildren()>=1)
         {
           num = g_delNode->getNumChildren();
           osg::ref_ptr<osg::Node> ptNode1;
           {
                   for(int i = num-1;i>=0;i--)
                   {
                           ptNode1 = g_delNode->getChild(i);
                           if(ptNode1.valid()&&tepview->m_pNodes!=NULL)
                           {
                                 ptGp->removeChild(ptNode1.get());
                                 if(ptNode1.valid()&&ptNode1->referenceCount()>0&& tepview->m_pNodes->containsNode(ptNode1.get()))
                                         tepview->m_pNodes->removeChild(ptNode1.get());
                           }
                   }

                   num = g_delNode->getNumChildren();
                   for(int i = num-1;i>=0;i--)
                   {
               ptNode1 = g_addNode->getChild(i);
                          if(ptNode1.valid()&&g_delNode)
                           g_delNode->removeChild(ptNode1.get());
                          while(ptNode1.valid()&&ptNode1->referenceCount()>0)
                                 {   
                                         ptNode1->unref();
                                 }
                   }
           }
         }
  traverse(node, nv);
         }
   }
};

该用户从未签到

 楼主| 发表于 2009-5-20 10:53:37 | 显示全部楼层
都几天了还是没有搞定,高手快帮忙啊,谢谢了!

该用户从未签到

 楼主| 发表于 2009-5-20 11:13:00 | 显示全部楼层
在ref()时有时也会报错!

该用户从未签到

发表于 2009-5-20 12:17:37 | 显示全部楼层
智能指针是非常出色的大大简化用户内存管理操作的工具,大量的用户已经反复验证过它的稳定性和正确性。所以恐怕是您的使用方法有误。

我无法理解的是,您为什么要手动unref()?这样很可能使得被管理的对象自动卸载,进而导致其它引用该对象的地方因出现野指针而崩溃

该用户从未签到

 楼主| 发表于 2009-5-20 13:05:44 | 显示全部楼层
呵呵……确实是自己对智能指针不熟悉,因为我想在根节点删除字节点后立即清空内存,所以才手动强行让其unref()的。如果不用的话,好象不能释放内存。

该用户从未签到

 楼主| 发表于 2009-5-20 13:08:15 | 显示全部楼层
请问Array大哥怎样作啊。

该用户从未签到

发表于 2009-5-20 14:28:19 | 显示全部楼层
不能释放内存的话,说明还有其他地方引用了这个对象,在那个地方removeChild()。

否则的话,因为强行unref()造成对象被释放,变成野指针。因而执行到另一处引用了该对象的地方时,必然会崩溃

该用户从未签到

 楼主| 发表于 2009-5-20 17:51:22 | 显示全部楼层
谢谢了,还是自己理解的不够深刻啊!估计是什么地方还在引用该节点,谢谢Array老大了!
  • TA的每日心情
    开心
    2019-11-11 10:36
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2009-5-20 20:53:32 | 显示全部楼层
    智能指针不用手动unref,简单来说智能的机制是:当前内容被引用的次数为N,当N为0时内存自动释放。

    该用户从未签到

     楼主| 发表于 2009-5-21 10:34:22 | 显示全部楼层
    呵呵……谢谢大家了,好像就是不能强行unref,不过问题解决了,是自己疏忽了,把一个变量定义成了全局变量,结果导致智能指针在调度期间不能自动释放内存,现在场景调度期间可以自动释放内存了,不过调度过程与预期的不对,程序启动后调度没有问题,当按下空格键时,调试信息中显示 msvcp71d.dll处最可能的异常0xc0000005结果就会出现应该加载到场景的东西没有加到场景中,由于调度算法是在另一线程中进行的,而在节点回调中进行的场景更新,会不会是两个线程发生冲突了,还是两个线程的同步问题啊?请高手帮忙分析分析,谢谢大家了!

    该用户从未签到

    发表于 2009-5-21 11:27:22 | 显示全部楼层
    呃,我无法猜测您遇到的问题。很可能是您自定义的线程和渲染线程发生了不同步的问题。OSG中线程同步的代码编写是很严谨的,因此如果您真的想自己实现动态调度,最好的方法还是继承DatabasePager写一个新的调度类,并setDatabasePager()给视景器Viewer

    不过我个人认为使用DatabasePager来实现动态调度是最好的选择

    该用户从未签到

     楼主| 发表于 2009-5-21 13:55:38 | 显示全部楼层
    好的,谢谢Array大哥了,我去看看吧!
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

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

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

    联系我们

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