В моем коде у меня есть класс SoundManager, который содержит и использует все звуки для моей игры. Этот класс должен быть создан, и его методы вызываются несколькими другими классами. Однако я хочу, чтобы в памяти присутствовал только один набор звуков, поэтому в интересах эффективности все ресурсы объявлены как static 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 справился с этим.
Кто-нибудь знает, что может быть причиной моей проблемы с уборкой?
Вы используете библиотеку IRRKLang. Эта библиотека поставляется в виде предварительно скомпилированного двоичного файла (dll, если вы находитесь на Windows). Эта библиотека делает себя двоичной совместимой благодаря использованию чисто виртуальных баз. Это работает, но вы не можете удалить объект для такой библиотеки, потому что ваша программа new / delete отличается от новой / delete библиотеки. Эти типы библиотек предоставляют способ освободить память, в данном случае это падение.
Чтобы использовать shared_ptr и т. Д. Вы должны использовать пользовательский удалитель. Взгляни на Использование пользовательского удалителя с std :: shared_ptr чтобы увидеть, как это сделать, и изменить его в соответствии с вашими потребностями.
В вашем случае, так как вы используете Visual Studio 2012, вы, вероятно, можете сделать что-то вроде этого
template<class T>
struct IrrDeleter{
void operator()(T* t){
t->drop();
}
};
затем измените все строки сброса, чтобы включить, например, удалитель
sEngine.reset(createIrrKlangDevice(),IrrDeleter<ISoundEngine>());
Если вы хотите вручную освободить ресурс, используемый shared_ptr
тебе нужно позвонить reset
. Что касается использования статического shared_ptr
Я не думаю, что я понимаю Все дело в том, что они не копируют ресурс, поэтому у вас будет только один ресурс.