Trouble with DX VertexBuffer using VisualStudio 2010

07b9e9e8483468e4a0e1bac1843e6e74
0
Snoob 105 Mar 15, 2012 at 12:16 directx

Actually I play arround with DirectX9 and Visual Studio 2010 and got trouble with VertexBuffer object
creation I can’t explain by myself:

I’ve a VertexBuffer class which creates an VertexBuffer object in c’tor initialization:

HRESULT hr = d3ddev->CreateVertexBuffer(this->getSize(),
                     0,
                     0,   // DON'T pass the FVF code we using vertex decleration
                     D3DPOOL_MANAGED,
                     &m_buffer,
                     NULL);
Note: m_buffer is a class Member: IDirect3DVertexBuffer9*  m_buffer;

This works fine and the buffer is initialized with following values:

  • m_buffer 0x028930c0 IDirect3DVertexBuffer9 *
  • IDirect3DResource9 {…} IDirect3DResource9
  • IUnknown {…} IUnknown
  • __vfptr 0x6e772720 *
    [0] 0x6e847490 *
    [1] 0x6e7760c3 *
    [2] 0x6e775a8d *

But when the c’tor is left I lost the refernce to the IUnknown ressource
immediately:

  • m_buffer 0x028930c0 IDirect3DVertexBuffer9 *
  • IDirect3DResource9 {…} IDirect3DResource9
  • IUnknown {…} IUnknown
  • __vfptr 0xfeeefeee *
    [0] CXX0030: Fehler: Ausdruck kann nicht ausgewertet werden
    [1] CXX0030: Fehler: Ausdruck kann nicht ausgewertet werden
    [2] CXX0030: Fehler: Ausdruck kann nicht ausgewertet werden

How this could be happend? This issue only occurs using Visual Studio
2010 express edition. If i compile the same code with gcc and codeblocks
everything is working fine …

This drives me nuts! Is there a restriction for MSVC DirectX Buffer
initialization I don’t know?

Thanks for any help.
Best regards,
Snoop

8 Replies

Please log in or register to post a reply.

07b9e9e8483468e4a0e1bac1843e6e74
0
Snoob 105 Mar 15, 2012 at 12:57

Ok, problem solved. The VertexBuffer was only created on stack. I don’t understood why, but when
the c’tor was left suddendly the d’tor was called and the buffer cleared. Creation of my class on heap
solves this problem…

Know’s anyone why in hell the buffer on stack is suddendly destroyed?

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Mar 15, 2012 at 18:24

So you created an instance of your own VertexBuffer class on the stack when this happened? Can you show us the code where you were creating/using it? Generally, the behavior you described (creating and immediately destroying) sounds characteristic of compiler-generated temporary objects. I wonder if you created your VertexBuffer object as a temporary and it did not get correctly assigned to a variable. For example, if you do not have a correct copy constructor in your VertexBuffer class and do something like this:

VertexBuffer myVb = VertexBuffer();

then you would get behavior like you describe, since the statement above creates a temporary VertexBuffer, then copy-constructs another VertexBuffer from it. Anyway, this is just a guess.

07b9e9e8483468e4a0e1bac1843e6e74
0
Snoob 105 Mar 15, 2012 at 20:11

This was my old initialization which works with GCC:

brDirectX::brD3D9VertexBuffer buffer = brDirectX::brD3D9VertexBuffer(brDataBuffer::USE_STATIC, sizeof(Vertex), sizeof(vertices)/sizeof(Vertex), device);

And yes the copy constructor is not implemented yet, so I think this must be the reason for the behaviour with MSVC.
I will check it.

Thanks Redbeeta

07b9e9e8483468e4a0e1bac1843e6e74
0
Snoob 105 Mar 15, 2012 at 20:42

The missing copy constructor was not the reason. I’ve added a copy constructor and an assignment operator implementation,
but this changes nothing.

brD3D9VertexBuffer::brD3D9VertexBuffer(const brD3D9VertexBuffer& vOther)
:brVertexBuffer(vOther)
{
    m_device = vOther.m_device;
    m_buffer = vOther.m_buffer;

    m_description = vOther.m_description;
    m_dxUsage    = vOther.m_dxUsage;
    m_lockMode    = vOther.m_lockMode;

    m_size = vOther.m_size;
    m_numVertices = vOther.m_numVertices;
    m_usage = vOther.m_usage;
}

When I create the buffer on stack with the command above the destructor is called immediately when
command is complete (including invoke of the copy c’tor)… Confusing is that this behaviour is only
happend on Vetex/Index buffer objects, I got no trouble with other DirectX wrapper classes (those
wrapper also have no copy c’tor).

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Mar 15, 2012 at 21:13

If you’re copying the pointer to the buffer, you also need to do an AddRef() on it. I presume your destructor is calling Release(), so you need to maintain the correct reference count when you make a copy of it.

Also, you could use different initialization syntax to avoid the temporary altogether:

VertexBuffer vb = VertexBuffer(some_params);    // creates a temporary, then calls vb's copy constructor to copy it
VertexBuffer vb(some_params);   // no temporary, calls vb's main constructor directly

If you need your class to be assignable and copyable, then of course implement the relevant functions, but you could also choose to make it non-assignable and non-copyable by making the assignment operator and copy ctor private. (And leave them unimplemented for good measure so that it fails even if you try to assign it or copy it from within the class itself.)

07b9e9e8483468e4a0e1bac1843e6e74
0
Snoob 105 Mar 15, 2012 at 21:58

I see! Thanks for the great explanation. Do you know if this is compiler specific behaviour?

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Mar 15, 2012 at 23:22

I believe the C++ spec only guarantees that a temporary lasts until you’ve finished evaluating the statement in which it’s created. It’s allowed for it to last longer, but you cannot depend on this. As you saw, in MSVC it really does destruct them as soon as that statement is over. It seems that in gcc, at least in this case, it was not destructing it until some later point (maybe the end of the function).

Fe8a5d0ee91f9db7f5b82b8fd4a4e1e6
0
JarkkoL 102 Mar 17, 2012 at 04:28

This is a case of return value optimization (RVO) that compiler may or may not apply in your case.