2013-04-17 2 views
-1

내 코드에는 내 게임의 모든 사운드를 포함하고 작동하는 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 (사운드도이 titlescreen 클래스에서 인스턴스화)를 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() 함수에 가깝게. shared_ptr이 이것을 처리 한 것으로 생각하기 때문에, 나는 이것을하기 전에 SoundManagers 멤버를 클린업하기 위해 어떤 종류의 액션도 취하지 않았습니다.

아무도 내 정리 문제를 일으킬 수 있다는 것을 알고 있습니까?

+2

어떤 종류의에 대한 귀하의 경우

는 Deleter가를 포함하는 모든 당신의 리셋 라인을 변경 당신은 아마이

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

같은 것을 할 수있는 비주얼 스튜디오 2012을 사용하고 있기 때문에, shared_ptr은 무엇입니까? 'std :: shared_ptr' 또는'boost :: shared_ptr'에서'reset()'을 호출하면'shared_ptr'이 제거되고, 객체를 참조하는 마지막 것이면 그 객체는 삭제 될 것입니다. 공유. – mark

+0

pooteners가 재사용되지 않습니까? 'sEngine-> addSoundSourceFromFile'가 같은 포인터를 두 번 반환하면 두 개의 다른'shared_ptr'에 할당하기 때문에 두 번 삭제됩니다. 서로에 대해 알지 못합니다.또는'sEngine' 호출이 포인터 중 하나에서 삭제되면'shared_ptr'은 더 이상 존재하지 않는 것을 정리하는 데 어려움을 겪습니다. 액세스 위반이 발생하는 포인터의 값을 적어두고 정확한 주소를 해제하려는 모든 삭제를 중단하십시오. –

+0

'boost :: shared_ptr'는'shared_ptr'이 유일하거나 참조 카운트를 얻는지를 결정할 수있는 멤버 함수를 가지고 있습니다. – mark

답변

1

귀하는 IRRKLang 라이브러리를 사용하고 있습니다. 이 라이브러리는 미리 컴파일 된 바이너리 (윈도우에있는 경우 dll)로 제공됩니다. 이 라이브러리는 순수 가상베이스를 사용하여 바이너리 호환이 가능합니다. 이것은 작동하지만 라이브러리 new/delete가 라이브러리의 새/delete와 다르므로 라이브러리와 같은 라이브러리의 객체를 삭제할 수는 없습니다. 이러한 유형의 라이브러리는 메모리를 할당 해제하는 방법을 제공합니다.이 경우이 경우 삭제됩니다.

shared_ptr 등을 사용하려면 맞춤 삭제기를 사용해야합니다. Using custom deleter with std::shared_ptr을보고 어떻게하는지보고 자신의 필요에 맞게 수정하십시오. 예를

sEngine.reset(createIrrKlangDevice(),IrrDeleter<ISoundEngine>()); 
+0

고마워, 내가 필요한 것 같아. 그렇다면 공유 된 데이터를 삭제하는 shared_ptrs 방식은 IRRKlang의 ISoundEngine의 범위를 벗어날 때 자신의 메모리를 관리하는 방식과 충돌합니다. –

+0

어쨌든. ISoundEngine에 대한 삭제 (shared_ptr 외부의 수동 인 경우에도)가 작동하지 않습니다. IrrKlang은 아마 다른 컴파일러/표준 라이브러리로 컴파일 되었기 때문에 삭제와 IrrKlang 삭제가 다르기 때문입니다. 모든 Irrklang 클래스는 올바르게 삭제할 drop 메소드를 제공하는 IRefCounted에서 파생됩니다. –

1

shared_ptr에서 사용하는 리소스를 수동으로 해제하려면 reset으로 전화해야합니다. 정적을 사용하는 것에 관해서는 내가 추론을한다고 생각하지 않는다. 요점은 리소스를 복사하지 않기 때문에 하나의 리소스 만 가질 수 있다는 것입니다.

+0

정적 인 포인터 shared_ptrs를 만들기로 결정했는데 전체 프로그램에서 포인터를 가리키는 객체의 인스턴스 하나만 있으면 좋겠지 만 여전히 SoundManager 클래스의 인스턴스가 여러 개있는 것입니다. 그러나 그것들을 'shared_ptr'로 만드는 것은 이것을하지 않습니다. 그래서 나는 그것들을 정적으로 만들었습니다. 이것이 나의 추론을 설명합니까? –

관련 문제