Public Group

Debugging a subtle bug

This topic is 3212 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hi, I have a subtle bug in my game and I'm at my wits end as to how to solve it. The application compiles and runs fine within visual studio but it's when I try to run the release build directly from the exe that the problem occurs. The problem occurs as the game is loading (on vista) the game starts loading things then the screen goes white and vista reports that it has stopped working. The wierd thing is that the error doesn't happen everytime, only now and again. I tried to find exactly where the game was crashing during the loading process by adding message boxes and I found that the problem occured here...
HRESULT AnimatedPlaneModel::LoadAnimationTextures(DWORD dwNumberOfTextures, std::string strFileName, HWND hWnd)
{
//	Negate 1 from the number of textures to help ease of use
m_dwNumberOfTextures = (dwNumberOfTextures -1);

// Create array on the heap to hold the textures
m_pAnimatedTextures = new LPDIRECT3DTEXTURE9[m_dwNumberOfTextures];
if( m_pAnimatedTextures == NULL )
return E_OUTOFMEMORY;

//  Create string stream to hold the filename
std::stringstream ssFileName;

for( DWORD i = 0; i <= m_dwNumberOfTextures; i++ )
{
// Add prefix Textures/ to the front of the filename, add the texture number and .dds to the end
ssFileName.str("");
ssFileName << "Textures/" << strFileName << (i + 1) << ".dds";

// Load the texture into the array pointed to by m_pAnimatedTextures
if( FAILED ( D3DXCreateTextureFromFileA(m_d3dDevice, ssFileName.str().c_str(), &m_pAnimatedTextures ) ) )
m_pAnimatedTextures = NULL;
}
// **** The error occurs here
return S_OK;
}

There is no code at that point other to return OK which is why I don't understand why it is crashing :-S . Does anyone know how I could go about debugging this problem? Any help would be much appreciated and I am happy to provide additional information or code. Cheers!

Share on other sites
Does a debug build also crash outside of VS? If so, you can attach the debugger to the process when the crash occurs and hopefully find out something more useful. You may need to enable JIT debugging to streamline the process.

Share on other sites
Consider

Quote:
 for( DWORD i = 0; i <= m_dwNumberOfTextures; i++ )

If the count is 2, you do a new LPDIRECT3DTEXTURE9[2]. So you have available slots m_pAnimatedTextures[0] and [1].

You then do the loop for(DWORD i=0;i<=2;++i) which yields 0, 1 and 2.

The loop of 2 accesses unallocated slot, which is undefined so may crash or may not depending on phase of moon, hence unpredictable behaviour.

Change the for loop condition from <= to <, and get more comfortable with zero-based indexing.

It would appear that the count parameter passed to this function is one greater than it should be. Why is this? Why do you need to decrement it at the top of the function? Why doesn't the caller pass the correct texture count?

Share on other sites
you may want to test to see if m_dwNumberOfTextures is greater then 0 or create an out put of some kind from the function to watch what happens

Share on other sites
For future reference, this kind of bug can be made not-subtle by using vectors instead of raw arrays and then enabling checked iterators. In probably 90% of the random crashes that I've seen this instantly shows where the problem is (YMMV of course).

Share on other sites
@jouley - The game does not crash when running independent of visual studio :-S

@Aardvajk - The reason for the decrement at the beginning of the function is because I wanted to make the code easier to use, in the main loop where this function is called, it is called like this...

if( FAILED (m_pGazelleModel->LoadAnimationTextures( 5, "Gazelle", m_hWnd ) ) )		MessageBoxA( m_hWnd, "Failed To Load Gazelle Textures", "Error", MB_OK | MB_ICONEXCLAMATION );

5 is passed in as the number of textures because I know that I want to load 5 textures in total, this number is then reduced in the LoadAnimationTextures function because it is being used with an array and I need to account for 0. So my code should load a texture into m_pAnimatedTextures[0] through to m_pAnimatedTextures[4], which I think it is doing, or have I made an error?

The odd things is that this funtion is called once before and doesn't seem to cause and issue?!

Share on other sites
@nemebean - funnily enough earlier I did try replacing the array with a vector but quickly became confused as to how to do it, I tried the following..

//  Create a vector of pointers to hold the texturesstd::vector<LPDIRECT3DTEXTURE9*> vAnimatedTextures;for( i = 0; i <= dwNumberOfTextures; i++ ){    vAnimatedTextures.pushback( m_pAnimatedTexture );}for( DWORD i = 0; i <= m_dwNumberOfTextures; i++ ){		// Add prefix Textures/ to the front of the filename, add the texture number and .dds to the end		ssFileName.str("");		ssFileName << "Textures/" << strFileName << (i + 1) << ".dds";		// Load the texture into the array pointed to by m_pAnimatedTextures		if( FAILED ( D3DXCreateTextureFromFileA(m_d3dDevice, ssFileName.str().c_str(), vAnimatedTextures ) ) )			m_pAnimatedTextures = NULL;}

This didn't work, which I think I can see why now lol but I couldn't figure out the correct way as to how I could use a vector. Any suggestions?

Share on other sites
STL Vector Reference; you've misspelled push_back. You might also want to use resize instead of push_back with a loop. Other than that, you can treat (in most cases) a vector as a raw array.

Also, as Aardvajk pointed out, C++ arrays are 0-based:
// Here, you create n textures:  Elements [0 n) are accessablem_pAnimatedTextures = new LPDIRECT3DTEXTURE9[m_dwNumberOfTextures];if( m_pAnimatedTextures == NULL )	return E_OUTOFMEMORY;// Here, you attempt to access elements [0 n].  The error here is that m_pAnimatedTextures[n] does not exist.for( DWORD i = 0; i <= m_dwNumberOfTextures; i++ )  // ...

Changing it to for( DWORD i = 0; i < m_dwNumberOfTextures; i++ ) should fix the problem.

Share on other sites
Thankyou very much everyone! With all your help I have managed to solve the bug, which was in deed to do with accessing outside of the array. The error has been fixed and I have replaced the array with a vector and will try to bare that in mind in the future. Thanks Again!

Share on other sites
You may need to deal with HRESULTs in order to use DirectX, but that doesn't mean it should influence your own code style. The C++ I speak sounds quite different:

// Do you really need to be precise about the type for the 'textureCount'?// Rule of thumb: use 'int' for integers unless you have a reason not to.// The function didn't use the HWND passed to it, so there's no reason to pass// it. Get rid of that.void AnimatedPlaneModel::LoadAnimationTextures(int textureCount, const std::string& baseFilename) {	// With the vector, there is no need to store a count of textures internally.	animatedTextures.clear();	for (int i = 0; i < textureCount; ++i) {		// By scoping the stringstream inside the loop, we adhere to		// good style (it's the same principle as not using a global		// variable where a local one would do), and it's automatically		// cleared each time through.		std::stringstream filenameStream;		filenameStream << "Textures/" << baseFilename << (i + 1) << ".dds";		LPDIRECT3DTEXTURE9 result = NULL;		// You shouldn't specify the 'A' yourself. Instead, make sure		// your project unicode settings are correct so that		// D3DXCreateTextureFromFile is mapped to		// D3DXCreateTextureFromFileA for you.		// Because we set the "default if failed" value first, we don't		// have to check for failure.		D3DXCreateTextureFromFile(device, filenameStream.str().c_str(), &result);		animatedTextures.push_back(result);	}}

Simpler, yes? :)

1. 1
2. 2
frob
16
3. 3
4. 4
Rutin
11
5. 5

• 13
• 13
• 61
• 14
• 15
• Forum Statistics

• Total Topics
632125
• Total Posts
3004250

×