【发布时间】:2013-04-17 14:51:58
【问题描述】:
在我的代码中,我有一个 SoundManager 类,它包含并操作我的游戏的所有声音。这个类需要被实例化,它的方法被多个其他类调用。但是我希望只有一组声音占用内存,所以为了提高效率,所有资产都被声明为静态 shared_ptrs。
#include "SoundManager.h"
static shared_ptr<ISoundEngine> sEngine;
static shared_ptr<ISoundSource> hoverSound;
static shared_ptr<ISoundSource> confirmSound;
static shared_ptr<ISoundSource> mainBGM;
static shared_ptr<ISound> bgmInterface;
SoundManager::SoundManager(void)
{
//first we need to create the irrKlang sound engine instance
if(!sEngine)
{
sEngine.reset(createIrrKlangDevice());
}
if(!hoverSound)hoverSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonHover.mp3"));
if(!confirmSound)confirmSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonConfirm.mp3"));
if(!mainBGM)mainBGM.reset(sEngine->addSoundSourceFromFile("Sounds/mainBGM.mp3"));
//set some default volumes
hoverSound->setDefaultVolume(1.0f);
confirmSound->setDefaultVolume(0.4f);
mainBGM->setDefaultVolume(0.5f);
}
SoundManager::~SoundManager(void)
{
}
这个 SoundManager 在我的 main() 函数中实例化,并且每次我需要加载标题屏幕(SoundManager 也在这个标题屏幕类中实例化)。一遍又一遍地初始化和销毁标题屏幕不会导致问题。静态 shared_ptrs 对象不会被销毁,因为它们仍在被 SoundManager 的主要函数实例使用。
现在这一切在运行我的游戏时运行良好。然而,当谈到干净地退出时,当上面的静态对象被拆除时,未处理的运行时异常(访问冲突)被抛出给我。 VS2012 的调试器将我指向 memory.h 中的一行。
private:
virtual void _Destroy()
{ // destroy managed resource
delete _Ptr; <<<<<<<<<The debugger points to this line
}
我的理解是,与 obj-c 类似,c++ shared_ptrs 使用引用计数器来确保对象不会被删除,直到不再存在需要使用它们的对象。我不明白是什么导致了这些错误。
也许我不应该省略一个重要部分:我的游戏是通过调用 exit(0) 退出的;尽可能靠近 main() 函数。在这样做之前,我没有采取任何行动来清理 SoundManagers 成员,因为我认为 shared_ptr 已经处理了这个问题。
有人知道是什么导致了我的清理问题吗?
【问题讨论】:
-
它们是什么类型的 shared_ptr?在
std::shared_ptr或boost::shared_ptr上调用reset()将清除shared_ptr,如果它是最后一个引用该对象的对象,则该对象将被删除,否则该对象仍然是共享的。 -
你确定没有重复使用这些指针吗?如果
sEngine->addSoundSourceFromFile两次返回相同的指针,它会被删除两次,因为您将它分配给两个不同的shared_ptrs,它们彼此不知道。或者如果sEngine在其中一个指针上调用delete,shared_ptr将很难清理不再存在的内容。记下导致访问冲突的指针的值,并尝试在任何尝试释放该确切地址的删除处中断。 -
boost::shared_ptr具有允许您确定shared_ptr是否唯一或获取其引用计数的成员函数。 -
@mark 我以为shared_ptr只有一种? (顺便说一句,我最初是用唯一的 ptrs 来做的,但它产生了同样的问题)。
-
@ArneMertz
sEngine->addSoundSourceFromFile()返回一个指向ISoundSource类型的新对象的指针。我决定创建指针 shared_ptrs 因为它们是静态的,并且我只希望在整个程序中它们指向的对象的一个实例,同时仍然具有SoundManager类的多个实例。sEngine或任何与此相关的对象是否有可能获得最初由shared_ptr管理的指针的所有权并将其删除,而原始拥有的 shared_ptr 对此有什么要说的?除非我在一个愚蠢的地方调用 reset()?
标签: c++ memory-management smart-pointers irrklang