Skip to main content
GameDev.net gamedev.net
🔒 Locked

DirectX problem - my C++ program freezes!

Started by Riccardo Bestetti Oct 21, 2012 at 1:45 PM 16 replies 4.6k views
Original Post
Riccardo Bestetti
Riccardo Bestetti
Hello!
I'm learning DirectX 9 programming, but I've got this problem: I'm simply trying to render 3 lines to represent the 3 axis in the 3D space, but the program I wrote freezes.

I have to open up the Task Manager and close Visual Studio (which during the debug says "Run-Time Check Failure #2 - Stack around the variable 'pVoid' was corrupted")

This is the source code:

Entry point:
http://pastebin.com/BbVdeeNR

AxisRender.cpp:
http://pastebin.com/CNBubgJM

AxisRender.h:
http://pastebin.com/au7j41gw

Thank you in advance for your help!
Asesh
Asesh
Seems like it's because you have not specified usage parameter when calling CreateVertexBuffer? You should also check the return value of Lock. Just went through my old code and this is what I had done:


CHECK_COM(m_pD3DDevice->CreateVertexBuffer(4 * sizeof(SVertexData), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_pD3DPlaneVertexBuffer, NULL));
CHECK_COM(m_pD3DPlaneVertexBuffer->Lock(0, 0, reinterpret_cast<void **>(&pPlaneVertexBuffer), 0));
pPlaneVertexBuffer[0] = SVertexData(-1.0f, -1.0f, 1.0f, 0.0f, 1.0f);
pPlaneVertexBuffer[1] = SVertexData(-1.0f, 1.0f, 1.0f, 0.0f, 0.0);
pPlaneVertexBuffer[2] = SVertexData(1.0f, 1.0f, 1.0f, 1.0f, 0.0f);
pPlaneVertexBuffer[3] = SVertexData(1.0f, -1.0f, 1.0f, 1.0f, 1.0f);
CHECK_COM(m_pD3DPlaneVertexBuffer->Unlock());


and @line 41: memcpy(&pVoid, Vertices, 6 * sizeof(AxisRenderFV)); you could do this instead: memcpy(&pVoid, Vertices, sizeof(Vertices));
hunpro
hunpro
Hi,
'memcpy(&pVoid..' has a (big) problem: pVoid is a pointer, and you wanto to copy data to where it points, not where the pVoid variable is stored. Use pVoid instead of &pVoid. With your current code, you overwrite pVoids value, so it points somewhere else, and trash some remaining memory after pVoid, so you end up with that mean message.
Riccardo Bestetti
Riccardo Bestetti
Ok, now there's another runtime problem.
Eccezione first-chance a 0x75e3c41f in DX9-Cube.exe: Eccezione di Microsoft C++: long nella posizione di memoria 0x003bf4fc..[/quote]
In english, it is something like
First-chance exception at 0x75e3c41f in DX9-Cube.exe: Microsoft C++ Exception: long in memory position 0x003bf3fc[/quote]
(the memory addresses change every time)

I've tried to set some breakpoints, and it seems that the problem happens when axis.Render() is executed, but it can't figure out what's going on wrong
hunpro
hunpro
I think i got this error once when i called DrawPrimitveUP() outside of the d3ddev->BeginScene() d3ddev->EndScene() pair. Just a wild guess.
L. Spiro
L. Spiro
You should be using the DirectX Debug Runtime, enabled via the DirectX Control Panel.
It will report more information on this and other errors.


L. Spiro
I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid
Khatharr
Khatharr
Whoa.

Hey, if you're writing a member function you can refer to members directly. The only time you need to say "this->m_Var" is when you have a function-local variable or argument named "m_Var" and you want to refer to the member variable instead of the local one.

You need to check return values of DriectX functions religiously. Probably your vbuffer isn't getting set up correctly.

As was mentioned earlier, since you're talking about an array there (not a pointer) you can just say "sizeof(Vertices)." That also protects you in case you make a change to the size of the array for some reason: You won't have to change the size calculations. (Also in the memcpy() later.)

You need to check the return value not just of lock, but of anything that can return an error. I know it makes the code look big and clunky, and you have to type a bit more than usual, but it will save you a LOT of problems in the long run:

1) It means that you're more aware of possible problem states before you're even done writing the code.
2) If a runtime error happens you get to know what's going on immediately instead of having to debug for an hour.
3) Chicks dig it. Really. You wouldn't believe how many women will flock to you just for checking all your return values.
4) A lot of libraries (like DirectX) use error codes to alert you to a temporary or correctable problem - you can recover from the error easily without the program crashing (or it might not even really be an error).

Something else to look at:
AxisRender::AxisRender(float p_lenght, DWORD color)
{
this->lenght = p_lenght;
}

should be:

AxisRender::AxisRender(float p_lenght, DWORD color) :
VertexBuffer(NULL),
d3ddev(NULL),
lenght(p_lenght),
color(color)
{
//NOP
}


Initializer lists run faster than initializations in the constructor function body. When you write a constructor you should copy and paste all your member variables into the initializer list and then set a default value for all of them there in the same order. Even include the ones that don't matter, like initializing your pointers to NULL - if you don't then the compiler will do it anyway behind the scenes. Doing this also means that won't have forgotten to initialize the member variable 'color'.

I haven't messed with DirectX for a month or two but I think in render_frame() you want to set up the camera prior to calling the axis render. In this case it should correct on the second frame, since the camera setup from the previous frame will be inherited, but generally you want to set up all your matrices and then do your render call, since rendering uses the existing matrix to draw pixels with.

Keep at it, boss. Good luck! smile.png
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
kauna
kauna

Even include the ones that don't matter, like initializing your pointers to NULL - if you don't then the compiler will do it anyway behind the scenes.


I think that the reality is worse, the compiler won't initialize your values to anything (and they will contain garbage) unless you are running debug build. In which case the pointers won't contain NULL either but something more debug friendly such as 0xcccccccc or 0xbaadf00d etc.

Otherwise, the points in this message chain is that OP should
- check the return values of the functions (look for MSDN which functions have return values).
- look for bad pointers. (For example, that map doesn't return NULL pointer).
- run the program step by step with a debugger
- use Direct3D debug libraries

Cheers!
Riccardo Bestetti
Riccardo Bestetti
Guys, thank you VERY much!
You have no idea about how much your advises are precious to me smile.png

Ok, so now I'm using Debug runtime, and I get this output by the debugger:
Eccezione first-chance a 0x7538c41f in DX9-Cube.exe: Eccezione di Microsoft C++: long nella posizione di memoria 0x0036f510..
Direct3D9: (ERROR) :DrawPrimitive failed.
Direct3D9: (ERROR) :Vertex shader declaration is not set
[/quote]
But, why? Why should there be an error about a vertex shader if I do not have one?

Also, I can't really understand this:

AxisRender::AxisRender(float p_lenght, DWORD color) : VertexBuffer(NULL), d3ddev(NULL), length(p_length), color(color){ //NOP}

Well, I understand it, but I'm curious to understand the low-level difference from this to assigning variables normally as I was doing smile.png


Hey, if you're writing a member function you can refer to members directly. The only time you need to say "this->m_Var" is when you have a function-local variable or argument named "m_Var" and you want to refer to the member variable instead of the local one.

I know, but I always to this, always in Java because I like to remove any small possibility of ambiguity
But if you tell me that removing this-> would make the code faster, I will definitely do it!

As was mentioned earlier, since you're talking about an array there (not a pointer) you can just say "sizeof(Vertices)." That also protects you in case you make a change to the size of the array for some reason: You won't have to change the size calculations. (Also in the memcpy() later.)

Yeah, I actually did this some minutes after posting the thread
Riccardo Bestetti
Riccardo Bestetti
No, I have not! Hahaha it was so easy!
I just forgot to set which FVF I was using during the rendering.

This single line solved all my errors

this->d3ddev->SetFVF(AxisRenderFVF);
kauna
kauna
Yes, FVF or the Flexible Vertex Format is one way to set the vertex declaration.
However, if you want to upgrade to D3D 10-11 some day, the vertex declaration is the way to go. The vertex declaration has also more freedom.

Cheers!
Khatharr
Khatharr
Sorry for the late reply, I'm only online occasionally. I'm really glad you got it working!


I know, but I always to this, always in Java because I like to remove any small possibility of ambiguity
But if you tell me that removing this-> would make the code faster, I will definitely do it!


I'm not sure that it would be faster since an object member has an offset based lookup in either case. I'd have to check the disassembly to see if there's a difference. The reason that I brought it up is that as a general rule you want to shy away from bringing customs from one language into another. If you're just coding as a hobbyist then it's not a big deal since you'll probably eventually just grow out of it (or not, but it's not bothering anyone). If you plan to code professionally then people will look down on that kind of thing because it makes the code larger and harder to read and it means that you're doing a lot of extra typing.

If you're concerned about ambiguity then it's good to remember that C++ is a very strongly typed language. The compiler will most likely tell you if you're doing something crazy. The naming convention that I've been using lately is working out well for me (Someone else on the forum suggested it and I tried it out. Thanks to them!).

Basically it's like this:
g_GlobalVariableName
a_ArgumentVariableName
m_MemberVariableName
localVariableName

Again, though, it's an issue of trying to find an efficient writing style rather than an issue of compiled code performance, so it depends on what your long term programming goals are (hobby vs career).
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.