1

I've had to completely rewrite this problem as I've found out a lot more about it now.

Background:

My programme is drawing some 3d objects under directx11. I have a class that contains the data, pointers, and functions needed to draw the required 3d objects. Everything was working well. I could create many different 3d objects and draw them wherever I wanted. Great!

Then I needed to put them in a container and into a vector so I didn't have to create each object manually, this was where the trouble started; it would crash 1 time in 5 or so.

Unhandled exception at 0x00C308C1 in SpritesNTextN3D.exe: 0xC0000005: Access violation reading location 0xFFFFFFFF.

It crashed when using vectors and maps. I continued this line of enquiry and tried using a pointer and new:

ThreeD_Cube* threed_cube_p;
threed_cube_p = new ThreeD_Cube;

This also caused it to crash when I ran its draw function.

threed_cube_p->draw(threeD, camera, d3dContext_mp);

However if created as a standard object:

ThreeD_Cube threed_cube_;

The draw function never crashes.

threed_cube_-.draw(threeD, camera, d3dContext_mp);

Likewise, creating a pointer to threed_cube_ works as expected.

Question:

What is new doing that the default constructor isn't. Is there anything I should be looking at to resolve this problem?

David
  • 1,050
  • 1
  • 16
  • 31
  • Where is `threed_cube_vec` ever *sized* ? the error your getting would seem to indicate it is empty, and using `operator [](size_t)` isn't going to bounds check it for you, unlike `.at(size_t)` – WhozCraig Jul 11 '13 at 15:43
  • You mean is the vector holding something? Yes, it definitely is as I can copy it to a new object. I just put it in a i = threed_cube_vec.size() loop and it has the same result. I hope I'm not mistunderstanding your comment. – David Jul 11 '13 at 15:47
  • 2
    I'm gonna take a wild guess and say it's not the `vector` implementation, but something in your code, most likely the implementation of `ThreeD_Cube`, that is the culprit. Are you obeying the [Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three)? – Praetorian Jul 11 '13 at 15:48
  • I concur with @Praetorian by what I see. Something is being eaten along the way, and it might be a shallow-copy of `ThreeD_Cube`'s members. – WhozCraig Jul 11 '13 at 15:52
  • That's not proof... vec[0] could be holding trash, including NULL pointers. When you go to copy, the copy constructor builds a new object, and may build a valid object in spite of trash as an input. Post some of your class definition: default and copy constructors, and definitions of worldCB_ and viewCB_. Also post the line of code that initializes vec[0] – Peter Jul 11 '13 at 15:52
  • Surely any problems caught within that would be invalidated by the fact I can copy the object out of the vector and have it work? I'm assuming there's nothing wrong with vector's implementation. Are there any other tests I could run to diagnose the problem? – David Jul 11 '13 at 15:55
  • If I create another vector and copy the contents of the previous vector, it also crashes. Wouldnt that disprove the error in the original vector theory? – David Jul 11 '13 at 15:56
  • Thanks for all the help so far by the way. I really appreciate the effort. I was hoping this was something far more obvious. – David Jul 11 '13 at 16:03
  • @David It doesn't necessarily prove anything. As Peter mentioned earlier, it may indicate that your copy constructor is silently *fixing* something that's wrong with the source object. Please post the definitions of all constructors of `ThreeD_Cube`, as well as its assignment operator and destructor definitions. – Praetorian Jul 11 '13 at 16:05
  • @David you need to post your class definition. Also, your Vector is capitalized - is it a custom implementation or std::vector? std::vector uses copy constructors when you add an object to it, and you may not have provided one in your 3D class / the default one is not adequate for your more complex members – im so confused Jul 11 '13 at 16:06
  • @Praetorian If my copy constructor is silently fixing something, wouldnt it also be silently fixed when copied into a new vector? Thanks for your input so far. I'll add my constructor information to the main post. – David Jul 11 '13 at 16:09
  • @AK4749 My vector is a ranged checked version (from Stroustrup's std_lib_facilities). I was also concerned that may have been the issue, so I commented his template and #define out and switched to using std::vector. Same issue. – David Jul 11 '13 at 16:11
  • @David No, Copy Assignment operator and copy constructor are different. Ah, well then it's 99.999999999999999% your class definition that is at fault (I assume you are using a decent compiler) – im so confused Jul 11 '13 at 16:12
  • 4
    It's SSCCE time! http://sscce.org/ – Roddy Jul 11 '13 at 16:12
  • All these need to be defined for a class with non-trivial memory allocation : http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) – im so confused Jul 11 '13 at 16:14
  • @Roddy I completely agree! I was hoping this would be something that all the experts here would pick out quickly and make me feel stupid for posting. I would love to make a simple example, however as you may guess, with DirectX11 graphics there are so many dependant relationships it'll take me ages to get it down to the core elements. I was hoping someone would be able to suggest a good method to test it further. I figured copying it in and out of vectors and to a separate class would be enough. – David Jul 11 '13 at 16:21
  • More information added. Map and array examples. Strangely the array works, but the map has the same issue.... I am about to go off to bed now, but I'm looking forward to seeing any other suggestions or ideas. Thanks again. – David Jul 11 '13 at 16:37
  • @David, well, when you construct a `ThreeD_Cube` then `initialize` will get called twice. Is that a problem? And those `vertexbuffer_`, `indexbuffer_` and 'colormap` things look worrying. What type are they, and what does `unload_base_pointers` and `unload_content` do? This looks like classic 'rule of three' problem so far... – Roddy Jul 11 '13 at 20:12
  • @Roddy It looks like that is the case from all the answers so far. Thanks for all your help, hopepfully I'll have a solution soon. – David Jul 12 '13 at 01:32
  • @Roddy My unload functions don't do anything right now, they have been commented out. initialize being called twice is interesting, I'll have to take a look at that. Well spotted. vertexbuffer, indexbuffer and colormap are all - ID3D11Buffer*. I realise pointers are often the causes of errors, however surely these same errors would occur with regular objects. – David Jul 12 '13 at 02:08
  • Is there a way to get this same crash occuring without using a vector? What is vector doing that I havent tried yet? – David Jul 16 '13 at 05:02
  • Ok, the same occurs when using new to create the object. I'm going to have to look into what new does differently. I will also rewrite the original question to see if that makes it clearer for people. – David Jul 17 '13 at 05:10
  • Question rewritten --------- – David Jul 17 '13 at 05:47

2 Answers2

1

It seems you have a good constructor, but bad/insufficient (default) assignment operator and bad/insufficient (default) copy constructor.

Let's see why some parts of your code works but some not:

//threed_cube_vec[0].draw(threeD, camera, d3dContext_); // doesnt work!!!

It tells you what's in threed_cube_vec[0] is a bad/corrupted object.

ThreeD_Cube test  = threed_cube_vec[0]; // But, if I copy it...

In this line, (for some reason) firstly the constructor is called, which gives you a good object. Then the "=" is called, partially the object is modified, but the object is still good since it was already good before the "="

ThreeD_Cube* test = &threed_cube_vec[0];

As for a pointer, it is the essentially object threed_cube_vec[0] itself, so still corrupted.

ThreeD_Cube test  = threed_cube_vec[0];
vector<ThreeD_Cube> test2;
test2.push_back(test);
test2[0].draw(threeD, camera, d3dContext_);

This does not fixed the problem as you said. "test" is a good object, but when you push_back(test) into test2, a copy is pushed back [if you change it to test2.push_back(std::move(test) , the problem could be gone]. Since the copy constructor is incomplete, the object in test2[0] is corrupted. Similar scenario happens with your map.

Conclusion: if an object is originated from the constructor, you get a good object; if an object is originated from a copy constructor, it is corrupted.

A quick test you can do: resize your vector after you declare it, the error should be gone temporarily.

digit plumber
  • 1,140
  • 2
  • 14
  • 27
  • Thanks for your reply initiator. I've added a copy constructor example to the main post. This works with no problems. I've tried calling resize on the vector then drawing, it crashes. If I create a new vector, resize it, then copy it in, it also crashes. Is there another test I can do to try this? If you want me to post these test results I can. – David Jul 12 '13 at 02:01
  • 1
    If you use gdb, break right after the line: ThreeD_Cube test = threed_cube_vec[0]; print out "test" and "thread_cube_vec[0]", and see if there are any difference. – digit plumber Jul 12 '13 at 05:24
  • I'm running Visual Studio 2012, so I'm not sure how I would do that. I think what I'll try and do is more tests when I have the time. I'd like to post a solution once I have it. I'm pretty sure its going to be something in the copying the object as people have pointed out. – David Jul 13 '13 at 01:03
  • 1
    For Visual Studio, you start debug mode using (ctrl +) F5 key, and step into your code and breaks with the F10 and F11 keys mostly. – digit plumber Jul 13 '13 at 04:49
  • Thanks, I'll take a look on Monday when I get the chance. – David Jul 13 '13 at 09:44
  • Updated VS2012 to the latestest version. Now it works most of the time, but sometimes crashes. I'm hoping that it was coincidence. I'm going to spend time looking at all the objects contained within the class and subclasses. If I still can't fix it, I'll look more into directx and see if it is something there. – David Jul 16 '13 at 04:14
0

Crash after m = XMMatrixIdentity() - aligment memory in classes?

This topic covers the answer to my problem. I eventually tracked it down to XMMATRIX causing crashes with new due to memory alignment.

Here's a shortened version of the problem:

void matrix_test_pointer()
{
    XMMATRIX* xmmatrix_p;
    xmmatrix_p = new XMMATRIX;
    *xmmatrix_p = XMMatrixIdentity(); // this is where it crashes
}

void matrix_test()
{
    XMMATRIX xmmatrix;
    xmmatrix = XMMatrixIdentity();
}

int main()
{
    string wait;

    matrix_test();
    cout << "matrix_test() completed.\n";
    matrix_test_pointer();
    cout << "matrix_test_pointer() completed.\n"; // If it does you are lucky :)

    cin >> wait;
    return 0;
}

Chances are matrix_test will complete but it will crash before pointer will complete.

Community
  • 1
  • 1
David
  • 1,050
  • 1
  • 16
  • 31