-1

私のコードには、ゲームのすべてのサウンドを格納して操作する SoundManager クラスがあります。このクラスはインスタンス化する必要があり、他の複数のクラスによって呼び出されるメソッドです。ただし、メモリを占有するサウンドのセットを 1 つだけにしたいので、効率を高めるために、すべてのアセットを 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はこのtitlescreenクラスでもインスタンス化されます)。タイトル画面の初期化と破棄を繰り返しても問題はありません。静的な 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 メンバーをクリーンアップするための何らかのアクションを実行していません。

クリーンアップの問題の原因を誰か知っていますか?

4

2 に答える 2

2

によって使用されているリソースを手動で解放したい場合は、shared_ptrを呼び出す必要がありますreset。static の使用に関しては、shared_ptr私はその理由を理解していないと思います。全体的なポイントは、リソースをコピーしないため、リソースは 1 つしかないということです。

于 2013-04-17T15:01:26.530 に答える
1

IRRKLang ライブラリを使用しています。このライブラリは、コンパイル済みのバイナリ (Windows の場合は dll) として提供されます。このライブラリは、純粋な仮想ベースを使用することで、バイナリ互換になります。これは機能しますが、プログラムの新規/削除はライブラリの新規/削除とは異なるため、そのようなライブラリのオブジェクトを削除することはできません。これらのタイプのライブラリは、メモリの割り当てを解除する方法を提供します。この場合は削除されます。

shared_ptr などを使用するには、カスタムのデリータを使用する必要があります。Using custom deleter with std::shared_ptrを見て、その方法を確認し、必要に応じて変更してください。

あなたの場合、Visual Studio 2012 を使用しているので、おそらく次のようなことができます

template<class T>
struct IrrDeleter{
   void operator()(T* t){
       t->drop();
   }
};

次に、すべてのリセット行を変更して、削除を含めます。たとえば、

sEngine.reset(createIrrKlangDevice(),IrrDeleter<ISoundEngine>());
于 2013-04-17T15:38:52.747 に答える