[Solved (probably)] OgreAL crash loading sound in Debug mode

Jekteir

23-07-2007 18:32:26

Hi, the Release build of my project (VC++2005) is crashing upon shutdown, but I can't debug that crash because my Debug build is crashing a little bit after load! I went into Debug mode for that crash, and it seems to be crashing after I try to load a sound with OgreAL (a sound which plays fine in the Release version).

Earlier in the code, in Core's constructor, I instantiated my OgreAL soundmanager, after Ogre's root was sorted out:


sndMgr = new OgreAL::SoundManager();


later, in the game loop, also in Core:


ogre->loadResources("sound");

OgreAL::Sound *sound = sndMgr->createSound("Killed", "killedhim.wav", false);
//node->attachObject(sound);
sound->play();


It's at this stage that the program crashes, and the debug stack trace looks like:


Client.exe!_free_dbg_nolock(void * pUserData=0x016cfad8, int nBlockUse=1) Line 1279 + 0x30 bytes C++
Client.exe!_free_dbg(void * pUserData=0x016cfad8, int nBlockUse=1) Line 1220 + 0xd bytes C++
Client.exe!operator delete(void * pUserData=0x016cfad8) Line 54 + 0x10 bytes C++
Client.exe!std::allocator<Ogre::FileInfo>::deallocate(Ogre::FileInfo * _Ptr=0x016cfad8, unsigned int __formal=1) Line 141 + 0x9 bytes C++
Client.exe!std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> >::_Tidy() Line 1098 C++
Client.exe!std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> >::~vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> >() Line 547 C++
Client.exe!std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> >::`scalar deleting destructor'() + 0x2b bytes C++
Client.exe!Ogre::SharedPtr<std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> > >::destroy() Line 201 + 0x2e bytes C++
Client.exe!Ogre::SharedPtr<std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> > >::release() Line 190 + 0xf bytes C++
Client.exe!Ogre::SharedPtr<std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> > >::~SharedPtr<std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> > >() Line 130 C++
Client.exe!OgreAL::SoundManager::_createSound(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & name="Killed", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & fileName="killedhim.wav", bool loop=false) Line 276 + 0x27 bytes C++
Client.exe!OgreAL::SoundManager::createSound(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & name="Killed", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & fileName="killedhim.wav", bool loop=false, OgreAL::AudioFormat format=DEFAULT) Line 217 C++
Client.exe!Core::initialise() Line 228 + 0x52 bytes C++
Client.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * __formal=0x00000000, char * strCmdLine=0x00152342, HINSTANCE__ * __formal=0x00000000) Line 250 C++
Client.exe!__tmainCRTStartup() Line 324 + 0x35 bytes C
Client.exe!WinMainCRTStartup() Line 196 C


Now, at the Ogre code from the above line:

Client.exe!Ogre::SharedPtr<std::vector<Ogre::FileInfo,std::allocator<Ogre::FileInfo> > >::destroy() Line 201 + 0x2e bytes C++


there's a comment in Ogre's code which reads:


virtual void destroy(void)
{
// IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
// BEFORE SHUTTING OGRE DOWN
// Use setNull() before shutdown or make sure your pointer goes
// out of scope before OGRE shuts down to avoid this.
delete pRep;
delete pUseCount;
OGRE_DELETE_AUTO_SHARED_MUTEX
}


Please note, however, that my program is not trying to shut down Ogre -- if any Ogre shutdowns are occurring they're due to OgreAL.

Would you be able to shed any light on which might be going wrong in this trace? The sound file in question is just a standard 44khz 16-bit WAVE file, with no spaces in the filename. It's not meant to be attached to an object -- it's just a test sound for during the flash screens. It's large, though: 63MB. It's a song :)

Thanks,

Jek

CaseyB

24-07-2007 02:39:48

The size shouldn't be a problem, it'll just eat up resources, but shouldn't crash. Is there anything in your Ogre.log that indicates what the problem maybe? Can you set a breakpoint at that line and step into OgreAL and find the line that's causing the trouble?

Jekteir

24-07-2007 18:05:47

The crash happens, in low-level terms, in

// TEMPLATE FUNCTION _Destroy_range
template<class _Ty,
class _Alloc> inline
void _Destroy_range(_Ty *_First, _Ty *_Last, _Alloc& _Al)
{ // destroy [_First, _Last)
_Destroy_range(_First, _Last, _Al, _Ptr_cat(_First, _Last));
}


This gets called in code that happens when OgreAL::SoundManager tries to return the NewSound from _createSound() to createSound().

The highest-level code that gets called before the crash is

OgreAL::Sound *sound = sndMgr->createSound("Killed", "killedhim.wav", false);

at the end of createSound() it does:

return _createSound(name, fileName, loop);

_createSound is fine until the last 3 lines at:

Sound *newSound = static_cast<Sound*>(mSoundFactory->createInstance(name, NULL, &mFileTypePair));
mSoundMap[name] = newSound;
return newSound;


It seems that on

return newSound;

it calls this function in OgreSharedPtr.h :


virtual ~SharedPtr() {
release();
}


It crashes with 'HEAP[Client.exe]: Invalid Address specified to RtlValidateHeap( 01420000, 016E6BF8 )'. The error message that pops up on-screen reads:

Debug Assertion Failed!
Expression: _CrtIsValidHeapPointer(pUserData)


-- OK, one of my team members tells me he got it to stop crashing. He set the resourceList variable null just before the exit of the function, and that seems to have cleared up the problem with that pointer's destructor later on. This is the pointer which gets initialised earlier in that function:

Ogre::FileInfoListPtr resourceList = mResourceGroupManager->listResourceFileInfo(group);
Ogre::FileInfoList::iterator itr = resourceList->begin();


His new ending for the function now reads:

mSoundMap[name] = newSound;
resourceList.setNull();
return newSound;
}


Do you think this is a problem with Ogre, or with how you're using that pointer; or is there a newer more eihort-friendly way of looking for the resource earlier in the function?


Jek

CaseyB

26-07-2007 18:06:08

That's very odd! Can you give me more info about how your using OgreAL so I can try to recreate the problem?

Jekteir

26-07-2007 18:36:00

Please let me know what additional information you need.

CaseyB

27-07-2007 18:31:14

I'd like to see how your initializing OgreAL and creating the sound. Other than that I have no idea, I've never seen an issue like this one!

Jekteir

27-07-2007 21:22:59

All I'm doing with the sound is described in my first post, where I quote the instantiation and the use of sounds I make. Nothing else happens with sound. I should re-emphasise that it only happens in Debug mode (and not any more, since I changed the code); my feeling is that this may have something to do with VC++ 2005 changing the values of null/uninstantiated/deleted pointers to something other than zero. I know Debug tends to set uninstantiated pointers to point to 0xcdcdcdcd -- got that when my program said something which hadn't been touched wouldn't delete, and I realised it thought it was an object because it was non-zero (I hadn't set it to null in the constructor). So maybe this has something to do with that?

Jekteir

30-07-2007 23:35:50

OK, think I figured this one out. A similar error came up in a different function of ours that used a DataStreamPtr. I saw this thread:

http://www.ogre3d.org/phpBB2/viewtopic.php?t=20116&view=previous&sid=ce193664e1d3d7c4af509e6f4e2718c6

and half-way down it mentions the linker setting 'Multi-Threaded Debug DLL (/MDd). We had our VC++ set on Multi-Threaded Debug (/MTd). It looks like on that build setting sometimes the wrong memory manager is called to try and destruct a pointer that was under the control of another memory manager. That, at least, is my understanding... So it looks like OgreAL was probably blameless, and this problem may go away with the original code in use now : )