Thread: problem setting/initializing/copying.reading arrays of meshes

  1. #1
    Registered User Vick jr's Avatar
    Join Date
    May 2009
    Location
    Galifray
    Posts
    27

    problem setting/initializing/copying.reading arrays of meshes

    ####short version###
    I have a mesh class which contains texture, material, and geometry data, as well as a float, "Bounding Radius".

    I am trying to have a class derived from the mesh class called "ObjectType".
    I initialize the array like so.
    Code:
    ObjectType* objectTypes=NULL;
    objectTypes=new ObjectType[2];
    objectTypes[0]=ObjectType(...arges...);
    objectTypes[1]=ObjectType(...arges...);
    the constructor ObjectType(...arges...) calls a (non-default) Mesh constructor to init it's mesh member variable. For debugging purposes, I made the default mesh constructor assign bounding radius a value of 5.0, but the non-default constructor, called by assign it a value of 7.0.

    But when trying to render the meshes in the array, I get an "Access violation writing location" and the material, texture, and geometry appears uninitialized, even though BoundingRadius is 7.0, indicating that the correct constructor was called and the other data should have been initialized as well.

    ####long version###
    I am making a simple 3d engine with directx.

    Basically I have a class, "scenario", which contains inormation on the world (gravity, camera, etc.)and an array of class "ObjectType".
    Class "ObjectType contains a member of class "Mesh" and an array of class "Object".
    Class "Object" contains transform information for an instance of its parent ObjectType mesh.
    class "Mesh" contains materials, textures, and geometry for a directx mesh. It loads this from a directx file.

    I tell my scenario to render, which loops through its object types and tells them to render each of their instances. For every element in the instances array, the ObjectType sets the directx world transform matrix to that of corresponding object array element and renders the mesh.

    Originally I had implemented all the functionality of class "scenario" directly in the main part of my program, and everything was working fine. For greater data encapsulation I made the 'scenario" class, and now I'm trying to just create an instance of that, and have all the information for my world contained in it. However, I'm running in to problems with uninitialized meshes.

    In the main program I have

    Code:
    Scenario* world=NULL;//global variable
    world=new Scenario(...);//I call this after initializing directx. ellipses is the arguments
    this constructor for Scenario then calls the following lines of code in its body after initializing "objectTypes", a pointer to an object of class ObjectType, to NULL in the initializer list:

    Code:
    objectTypes=new ObjectType[2];//supposed to allocate memory for array of ObjectType objects.
    I have found that this line calls the default constructor of ObjectType 2 times (each of which also calls the default constructor for Mesh).
    (in the call stack, the default constructor of ObjectType was called by 'eh vector constructor iterator')

    Code:
    objectTypes[0]=ObjectType(...);//elipses is args telling it what file to load for the mesh and some other stuff
    This line calls the correct constructor for ObjectType which in turn calls the correct constructor for Mesh. It then calls the destructor for objectType which calls the destructor for mesh. (I assume it destroys whatever was already in the array, and creates a new object to put in its place, but apparently not in that order)

    After this, i would think that everything has been initialized. The main program then goes into the render loop, but when it tries to render the meshes of the ObjectType array it gets the following:

    Code:
    Unhandled exception at 0x4fe5799b in DXTest.exe: 0xC0000005: Access violation writing location 0xfeeefe9e.
    The actual addresses probably aren't important. The line that causes this is
    Code:
    g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] );
    which is supposed to set directx to use the texture for the mesh. In debug, the geometry,materials,and texture data for the entire mesh appears to be uninitialized, however, another member which i made is initialized with the value that the correct (not default) constructor gave it.

    Is this a problem with membership copy or something? Should I try making a function ObjectType::set(ObjectType) in which I copy all the data myself?

    Thanks for any and all help!

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I would suggest dynamically allocating each individual ObjectType, i.e. using something like this:
    Code:
    ObjectType** objectTypes=NULL;
    objectTypes=new ObjectType*[2];
    objectTypes[0]=new ObjectType(...args...);
    objectTypes[1]=new ObjectType(...args...);
    This will skip over any issues that you might have with copying ObjectTypes or default-constructing them. It also makes sense since ObjectTypes seem to be a fairly expensive object that you may want to pass around in your code as pointers, not copies.

    Also, try recompiling your whole code base (make clean or create a new project or whatever) . . . you'd be surprised how many memory errors like this can be fixed in this manner.

    Do you have more than one thread executing? Are you sure that the i variable has either 0 or 1? How exactly was g_pMeshTextures initialized?

    Other than that, you'll have to post some more code. There are any number of things that might have gone wrong, but we'd have to see code to be sure.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I would second what dwks has stated about using dynamic memory here. It will most likely solve a lot of the problems you are having which appear to be related to incorrectly copying objects. Personally I only use instances and the stack for small objects. STL containers perform very well with pointers and not so well with instances of objects since by their very nature they do a lot of copying internally.

  4. #4
    Registered User Vick jr's Avatar
    Join Date
    May 2009
    Location
    Galifray
    Posts
    27
    Quote Originally Posted by dwks View Post
    I would suggest dynamically allocating each individual ObjectType, i.e. using something like this:
    Code:
    ObjectType** objectTypes=NULL;
    objectTypes=new ObjectType*[2];
    objectTypes[0]=new ObjectType(...args...);
    objectTypes[1]=new ObjectType(...args...);
    This will skip over any issues that you might have with copying ObjectTypes or default-constructing them. It also makes sense since ObjectTypes seem to be a fairly expensive object that you may want to pass around in your code as pointers, not copies.

    Also, try recompiling your whole code base (make clean or create a new project or whatever) . . . you'd be surprised how many memory errors like this can be fixed in this manner.

    Do you have more than one thread executing? Are you sure that the i variable has either 0 or 1? How exactly was g_pMeshTextures initialized?

    Other than that, you'll have to post some more code. There are any number of things that might have gone wrong, but we'd have to see code to be sure.
    Thank you! Dynamic initialization works perfectly. There's no double initialization and so no need for any copying. You're right, this is better in the long run anyway. (you learn something new every day!)

    My theory is that when i was trying to assign values to my objects using for form
    Code:
    ObjectTypes[i]=ObjectType(...args...);
    it would create a new objectType using the constructor, delete the old one, copy the member variables, and delete the one it just created. (Even though compilers have the option to optimize by creating the new object directly in the memory where it will be used in cases like this)
    The problem was that those member variables were pointers, and since it just deleted the data of the original object they pointed to, they no longer worked and were creating errors. Moral of the story: don't copy pointers and try to use them unless you're sure the data they point to is still valid.

    problem solved.

    One more thing: to delete that array, I would use
    Code:
    delete[] objectTypes;
    in the the destructor correct?

    Thanks again!

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Yes -- if you use new[], you must use a corresponding delete[]. But if you also allocate each pointer with new, then you'll have to actually use something like this:
    Code:
    for(int x = 0; x < ELEMENTS; x ++) {
        delete objectTypes[x];
    }
    delete [] objectTypes;
    [offtopic] By the way, if you ever run into this issue of memory management of pointers again in a way that is not so easily resolved, you could look into smart pointers. I really like Boost's implementation of smart pointers: shared_ptr

    The basic idea is that for every dynamically allocated pointer you maintain a reference count. Every time the object is copied you increment the count; when a copy is destroyed you decrement the count; and when the count hits 0 you free the object. [/offtopic]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you do decide on boost keep in mind the STL containers don't work all that well with it. When the boost pointer goes out of scope in your STL container it will clean up, however, the container will not remove the invalid pointer from the container unless you specifically remove it or use a boost custom deleter that removes the pointer from the container. Also if you are using DLLs be careful not to expost boost across the module boundary unless you are 100% sure that the client of the DLL and the DLL will use the same exact compiler version. Even with that you must be careful with boost b/c if you return a boost pointer from a DLL the boost pointer could clean up outside of the DLL which could potentially cause problems.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with Arrays
    By dldsob in forum C++ Programming
    Replies: 4
    Last Post: 10-28-2009, 08:43 PM
  2. assignment of arrays problem
    By HumbuckeR in forum C++ Programming
    Replies: 4
    Last Post: 04-13-2006, 04:25 PM
  3. Problem with arrays
    By dogbert234 in forum C++ Programming
    Replies: 2
    Last Post: 03-25-2006, 03:06 AM
  4. Problem with character arrays in classes
    By spoketoosoon in forum C++ Programming
    Replies: 3
    Last Post: 03-16-2004, 03:57 AM

Tags for this Thread