Runtime error (revised)

Started by
7 comments, last by BreathOfLife 16 years ago
OK, im getting an exception when i try to run my C++ coded program. There is a source file for the window stuff, and the DX stuff is all stashed in another .cpp. The project compiles and links just fine, but when i try to run it, im getting an exception. Im using visual C++ 2008 express. int DX_GFX_INI() { HRESULT hr; d3d = Direct3DCreate9(D3D_SDK_VERSION); if (!d3d) { return 0; }; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = FALSE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hWnd; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; d3dpp.BackBufferWidth = SCREEN_WIDTH; d3dpp.BackBufferHeight = SCREEN_HEIGHT; hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3d_device); if (FAILED(hr)) { return 0; }; hr = D3DXCreateSprite(d3d_device, &d3d_sprite); // create the Direct3D Sprite object if (FAILED(hr)) { return 0; }; return 1; } void DX_GFX_FRAME() { // clear the window to a deep blue d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3d_device->BeginScene(); // begins the 3D scene d3d_sprite->Begin(D3DXSPRITE_ALPHABLEND); // begin sprite drawing //drawing! d3d_sprite->End(); // end sprite drawing d3d_device->EndScene(); // ends the 3D scene d3d_device->Present(NULL, NULL, NULL, NULL); } That is the code that is in the directx handling source, and the line that is causing the error is the d3d_device->Clear call. I posted before but delete after i realized i had very little the way of checking if d3d even got created correctly, so i changed the GX_GFX_INI around a little bit, and then in the windows source there is a function whose body is as such. void SOL_INI() { if(!DX_GFX_INI()) { PostMessage(hWnd, WM_DESTROY, 0, 0); }; } Unless im wrong, i figure this would destroy the window, and thusly end the program (the postmessage is what i use on a VK_SPACE hit to close it otherwise). This all seemed to work just fine when it was all in the same source, but even after re-writing most of it for 2 files i just cant figure it out... [Edited by - BreathOfLife on March 24, 2008 9:02:07 PM]
Advertisement
If you're getting an exception on a member function call from an interface pointer, there's a good change your pointer doesn't actually point to anything. The easiest way to check this is use the debugger to have a peek at what the value of your interface pointer is. In Visual C++, this means just breaking into the debugger when the exception is caught (click retry) and the putting your mouse over the pointer to see its value. In debug builds, uninitialized variables are typically given a value of 0xcccccccc.

And as for destroying your window, use DestroyWindow instead. It does a bit more than just posting a WM_DESTROY message.

EDIT: one more thing...if you're posting long bits of code you can use the "source" tags to make it come out pretty
OK neat, didnt know thats exactly how the debugger could be used. Anywho, the value of my d3d is 0x00163f60, but both my d3d_device and d3d_sprite are 0x00000000, and i dont know what that means.

Also, when i mouseover my hWnd, and click on the little menu + thing, what pops up has a ! symbol and says CXX0030 "expression cannot be evaluated"

OK, one last fiddling with stuff edit before the bed wins the war, d3d_device has a + menu thing too, IUnknown, which also has a +, which brings up __vfptr, which also has the CXX0030 "expression cannot be evaluated"

[Edited by - BreathOfLife on March 25, 2008 1:58:43 AM]
0x00000000 means that its null. I don't know DirectX so I could be missing something but you have a d3d variable and a d3d_device variable. Is there a difference?
As Stormtrooper mentioned, in Windows 0x00000000 == 0 == NULL. Pointers are never initialized to NULL on their own in C++, so this means you've initialized d3d_device to NULL and then tried to use it. And as you probably already know, you can never call a method on a NULL pointer or dereference in any other way. The most likely cause of this would be that you're somehow calling "DX_GFX_FRAME" before you call "DX_GFX_INI". Are you calling these in response to Win32 messages?

As for what you're seeing with the debugger, let me explain a bit for you. When you've broken into the debugger, you can peek at at your variables in two ways: you can look at the list of local, automatic, or watched variables in the bottom left window (local variables are variables local to the function, automatic variables are variables referenced or changed recently, watched variables are variables you've manually tagged as such), or you can hover your mouse over a variable. What you see when you either look at the variable in the window or when you hover over it depends on what kind of variable it is. If it's a regular primitive type (int, short, float, etc.) you just see the value. If it's a struct or class, you get a little plus icon and you get a little tree that shows the values of all of the members of a class or struct. Here, let's take a simple example and I'll show you a picture of what happens in the debugger: try making a simple console program and declare a struct with a few members. Then in the main function create a few primitive types and assign them, then declare a variable whose type is your new struct and set its members to some arbitrary values. I'm going to use code that looks like this:

struct SuperStruct{	int memberA;	float memberB;};int main(int argc, char* argv[]){        int num1 = 47;	char char1 = 'A';	SuperStruct structInstance = {0};	structInstance.memberA = 99;	structInstance.memberB = 1.0f;	return 0;}



After this, put a breakpoint on the last "return 0" statement. You do this by clicking in the margin to the left of all of your code, you should see a red circle appear there. A breakpoint tells the debugger to break in as soon as it reaches that line, so you can have a look around. Now run your program, and either mouse over num1 or look down in the "autos" or "locals" tab of your debugger watch window. The debugger should show you that the int's value is 47, and should show you the char's numerical value as well as the corresponding ASCII glpyh. Now do the same for structInstance. You should get that little plus icon you saw before, except this time if you click on it you should get a list of structInstance's members and their values. Neat, right? Now at this point you hit F5 to resume execution and have your program wrap itself up, or you can hit F10 or F11 to step forward one line and see all of the stuff that the CRT does (the difference between F10 and F11 is that F11 will enter functions, while F10 will skip over them and go to the next line).

Okay now, moving right along. You can see how the debugger treats normal primitive types as well as structs and classes. But how about pointers? When the debugger hits a pointer, it will show you two things since both are probably relevant: the actual value assigned to the pointer, and the value of whatever the pointer is pointing to. Let's try it with both a primitive type and our struct. Change your code to this:

int main(int argc, char* argv[]){	int num1 = 47;	int* numPtr = &num1;	char* string1 = "Booga!";	SuperStruct structInstance = {0};	structInstance.memberA = 99;	structInstance.memberB = 1.0f;	SuperStruct* structPtr = &structInstance;	return 0;}


Now set your breakpoint again (if you removed it) and run your program. First check out numPtr: you should get a plus icon and then a value that's in hex. That hex value is the value currently assigned to your pointer, for me it's 0x0012ff60. The reason it's in hex is because pointers *generally* contain virtual addresses, with that address belonging to whatever they're pointing to. So in this case it's pointing to a local integer, so it's pointing to an address on the stack (if you don't know how the stack works don't worry about it right now). Now, click on the plus icon: lo and behold, we have a magic value "47" which is the value of the original integer. This means the debugger followed (derefrenced) the pointer and looked at the value in the memory address contained in the pointer. Now, have a look at string1: notice the debugger automatically interprets char* pointers as strings, and shows you the corresponding ASCII text. And finally, look at the struct. As expected, you get the value of the pointer in hex and then a full listing of the members when you click on the plus.

At this point, you should be able to start piecing together the behavior you were experiencing when you ran the debugger on your D3D app. You said you got a value of 0x00000000 when you moused over your d3d_device variable (which is a pointer of type IDirect3DDevice9*). Like I said earlier this meant the pointer was pointing to NULL, which basically means the pointer wasn't pointing to anything. Therefore when you clicked the plus the debugger followed this bogus pointer, found nothing, and then complained to you for making it do that. As for the HWND...that's a bit trickier. First it helps to see what an HWND actually is. For this we take a trip over to the MSDN library, which has a list of all of the types defined in the Windows API. There we find this:

typedef HANDLE HWND;


Okay...so what's a HANDLE? That's on the same page:

typedef PVOID HANDLE;


Ah hah, now we're getting somewhere (PVOID is just another typedef to void*). So what does this mean? To the debugger, an HWND is just a pointer. But in reality, an HWND is not a pointer at all: it's a handle to a window. It's value isn't a memory address we can just go to and find something relevant, it's a value that only has meaning for the OS window manager in user32. Which is why when the debugger tries to follow the pointer it finds garbage, and subsequently gets irritated.

Okay, so you're now a debugging master! Or, something like that. [smile]
You may notice I haven't really explained what's going on with that IUnknown that popped up, and also didn't mention what happens if you click the plus on actual valid IDirect3DDevice9 pointer. That's because the answers to these questions involve COM, and COM tends to be somewhat scary for beginner programmers. So I'll spare you for now, and instead suggest that you read the introduction to COM that's found a the beginning of the SDK documentation. It does a decent job of explaining COM in a way that's relevant to D3D. Don't worry if you don't understand all of it, just try to grasp the basics and come back to it as you become more experienced.

[Edited by - MJP on March 27, 2008 7:09:39 AM]
Quote:Original post by Stormtrooper
0x00000000 means that its null. I don't know DirectX so I could be missing something but you have a d3d variable and a d3d_device variable. Is there a difference?


Don't worry about that. With D3D you get a pointer to an IDirect3D9 interface that represents the general D3D9 SDK, and also a pointer to an IDirect3DDevice9 that represents the actual graphics device you're using.

OK, first off, thank you for the debug 101 diddy there, tons of neat stuff there.

Im not exactly sure how reading anymore documentation is going to particularly help me with my dilema. I dont really desire a deep understanding of anything other then why I cant use a call to clear() when i have multiple .cpp vrs just 1 source file. After that, the d3d stuff is more or less there to simply have output so i can work on more other things.

Google has no results, and thinking back I have in fact read up on COM (some tutorial before comanded it). I cant seem to get this to work...
What I would do if I were you is simply step through your app with your debugger and see how your program executes. Set a break point at your first line of code in WinMain, then see what functions your program runs and it what order. Or if you don't want to go through the whole program, just set breakpoints at the start of your DX_GFX_INI and DX_GFX_FRAME functions and make sure DX_GFX_INI is getting called first (I suspect your problem is that DX_GFX_FRAME is actually getting called first, hence the NULL pointer).
This is cryptic... the DX_GFX_INI() is literally just a carbon copy of the one that works just fine in the single source-file version, with only the pointer names changed, and the working on has hWnd passed as a paramiter (as in that case it is not global.

Is that the difference? Is it just that easy to keep passing hWnd as a paramiter in nested function calls?

I walked through both programs line by line, and in the one that works, when the function is done, the values of the pointer are all set to something, but in the problem project, all but d3d stay at null.

Then I learn aboot the directx debug stuff, but cannot find access to this control panel at all, although I am fairly certain that the only change is the debugger is going to tell me that the CreateDevice call failed...

This topic is closed to new replies.

Advertisement