[fixed] Application Crash with DirectX on Windows 2003

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
Smuel
Posts: 14
Joined: Fri Dec 08, 2006 10:50 am

[fixed] Application Crash with DirectX on Windows 2003

Post by Smuel »

I've just downloaded Irrlicht 1.2 and IrrWizard 1.1, and have been playing around with them. I got all four wizard modes to compile in Visual Studio 7.1, but when choosing DirectX as the display mode, the application crashes. The line is:

Code: Select all

m_pDevice = createDevice(EDT_DIRECT3D8, core::dimension2d<s32>(800, 600), 16, true, false, true, this);
If I specify OpenGL, or either of the software renderers, it works without crashing:

Code: Select all

m_pDevice = createDevice(EDT_OPENGL, core::dimension2d<s32>(800, 600), 16, true, false, true, this);
This is the call stack on the crash:
Visual Studio 7.1 wrote:Unhandled exception at 0x1000706f in Lite.exe: 0xC0000005: Access violation reading location 0x00000000

Irrlicht.dll!1000706f()
Irrlicht.dll!10006df5()
Irrlicht.dll!100ce4c5()
Irrlicht.dll!100aa25d()
ntdll.dll!7c82f9dd()
Irrlicht.dll!100aafe6()
Irrlicht.dll!100abd74()
Irrlicht.dll!100ac2b2()
Lite.exe!CGameManager::CreateDevice() Line 67 + 0x31 C++
Lite.exe!CGameManager::CGameManager() Line 30 C++
Lite.exe!CGame::CGame() Line 17 C++
Lite.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * __formal=0x00000000, char * strCmdLine=0x001420bd, HINSTANCE__ * __formal=0x00000000) Line 26 C++
Lite.exe!WinMainCRTStartup() Line 251 + 0x30 C
According to dxdiag.exe, I have DirectX 9.0c installed. My graphics card is pretty lame, but in any case my system config is besides the point - irrlicht.dll shouldn't crash if it doesn't like the DirectX features it finds - it should just return NULL for the device.

I don't yet have the DirectX SDK installed, so I can't compile irrlicht.dll and look at the code where it's crashing, but the addresses in the call stack above might be enough for someone to take a look at the problem.
Smuel
Posts: 14
Joined: Fri Dec 08, 2006 10:50 am

Since nobody responded I had to fix it myself. ;)

Post by Smuel »

Okay, I've installed the DX9 SDK and found the reason for the crash. It's in here:

Code: Select all

bool CGUIFont::load(io::IReadFile* file)
{
	return loadTexture ( Driver->createImageFromFile ( file ),
						file->getFileName()
							);
}
This crashes because Driver is NULL. To fix it, add two lines (marked with + below) after line 375 of CIrrDeviceWin32.cpp:

Code: Select all

    createDriver(driverType, windowSize, bits, fullscreen, stencilbuffer, vsync, antiAlias, highPrecisionFPU);
+   if( VideoDriver == NULL )
+       return;

    createGUIAndScene();
You should also initialize a couple of variables to NULL in the constructor for CIrrDeviceStub (after line 25 of CIrrDeviceStub.cpp):

Code: Select all

    UserReceiver = resv;

+   GUIEnvironment = NULL;
+   SceneManager   = NULL;

    Logger = new CLogger(UserReceiver);
If you make these changes, then irrlicht.dll no longer crashes if it can't initialise the 3D device. Of course - the IrrWizard code immediately crashes, because it assumes that the device creation worked and uses the NULL pointer. You guys should really get into the habit of returning and checking error codes...

Aside from these teething problems, this looks like a great project. I'm looking forward to using it some more.
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Now, it's far better to check these pointer right before accessing them, so I added it to CGUIFont methods. And the inits are of course done in the member init during object creation. Thanks for reporting the errors :D
Smuel
Posts: 14
Joined: Fri Dec 08, 2006 10:50 am

Knowing A Better Way is no substitute for testing.

Post by Smuel »

Well, you say that the inits are done somewhere, but when I ran the irrlicht DLL in debug mode those variables were 0xcdcdcdcd when it came to the drop() function, which then tried to drop() them and that crashed.

Also, if you don't want to include my test for VideoDriver being NULL, try setting it to NULL at that point and see if the DLL handles it subsequently. You might need some more checks...
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Check the latest SVN revision and you'll find the changes I made to fix those things. I just mentioned a slightly different style where I applied those changes compared to your suggestions. But they are basically the things you found :lol:
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

The actual problem is that the the device initialization code continues to run after it was unable to create a video driver. If the driver fails to init, then the createDevice() call should fail without continuing to initialize other subsystems. You will get the error described if the driver you request is not compiled into the dll. I know, I just tried it with a custom build of Irrlicht 1.2.

The fix that is done is nice and all [not really], but the underlying problem is not being addressed.

Code: Select all

// create driver
createDriver(driverType, windowSize, bits, fullscreen, stencilbuffer, vsync, antiAlias);

// add this to fix the actual problem. similar code exists in the linux driver
if (!VideoDriver)
  return;

createGUIAndScene();
IMO It is silly to add NULL pointer checks everywhere, and it can become very expensive. Something like a NULL pointer check should be done once at initialization/creation and never again. Also, if you must do a NULL type of check, you should consider using the NULL object idiom.

Travis
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

There's some system code after the GUI and Environment call which might be necessary to be executed, thus I'd rather use if (Driver) in that case. However, CGUIFont also requires a proper check because it might be called elsewhere and would then crash again. I think the checks had been in there some time ago, but were lost during the integration of antialiased fonts.
Post Reply