0

I'm having trouble with retrieving some values from a struct. In the below simplified snippets, struct Model's vertices member contains an array of values that can be retrieved correctly if buildModel() is called with drawModel() called within it. However, if I call buildModel() and then drawModel() afterwards, there are no errors, but the vertices are not retrieved with the correct values. This leads me to believe either a variable scope ended, I am passing the references incorrectly, or the vertices member needs to be defined on the heap with malloc.

MODEL.H:

typedef struct Model{
   Vertex *vertices;
} Model;

Model* newModel();

Model* setVertices(Vertex *vertices, Model *model);

MODEL.CPP:

Model* newModel(){
   Model* model;
   model = (Model* )malloc(sizeof(Model));
   //model->vertices = (Vertex *)malloc(sizeof(Vertex)); This did not help...

   return model;
}

Model* setVertices(Vertex *vertices, Model *model){
   model->vertices = vertices;

   return model;
}

DRAWING.CPP:

Model* buildModel(){
   Model* model = newModel();

   Vertex vertices[] = {
      { XMFLOAT3(-1.0f, 5.0f, -1.0f), (XMFLOAT4)colorX},
      ...  //Abbreviated declaration
   };

   model = setVertices(vertices, model);

   //drawModel(model);    Calling drawModel() here retrieves vertices correctly

   return model;
}

void drawModel(Model *model){
   loadVertices(d3dDeviceRef, 11, model->vertices); //Trying to pass vertices array here
}

This has been very useful in learning, and am trying to use as few classes as possible and go more the C route than C++ when I can.

Any help would be much appreciated,

Thanks.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
user176692
  • 780
  • 1
  • 6
  • 21
  • 1
    If you want to "go the C route", use C, not C++. Otherwise use the features a language provides. Anyway, this is C++, so do not use C tag. C and C++ are **different** languages. – too honest for this site Jan 19 '16 at 15:51
  • And there is no array member shown. A pointer is not an array and vice-versa! – too honest for this site Jan 19 '16 at 15:51
  • @Olaf Will try using C again soon, Visual Studio was preventing me from using it based on some of the libraries I was working with. In the meantime, it seems some C solutions can also work in C++. Like David Heffernan's answer [here] (http://stackoverflow.com/a/8224387/1914293) said `malloc` could be used in C++ but `new` is expected. Totally agree about taking a language seriously, still learning though, even from your comments. – user176692 Jan 19 '16 at 17:32
  • **Do not compile C code with a C++ compiler!** C has evolved a lot, as has C++. Note that C means at least C99, but actually standard C, which is **only** C11 (there are no multiple C standards). Even for identical syntax&grammar some semantics differ subtle, but significantly. The common subset of both languages is too small to write good non-trivial code in any language. A generalised personal note: I would refuse any code from a student or co-worker which sacrifices language features which enhance code-quality for the sake of compatibility. – too honest for this site Jan 19 '16 at 17:54
  • @Olaf Semi-compatible code is a bad idea, but have had intention of re-writing with what I learned one day. Instead of just using the above for personal use, keeping co-workers or a teacher in perspective as a user is an excellent idea. – user176692 Jan 19 '16 at 18:29

2 Answers2

3

The vertices array is local to the buildModelfunction. As soon as the function returns, the array is gone.

This is equivalent to returning a pointer to a local variable, just a bit more complicated.

I would recommend the C++ way, and use a std::vector instead of a bunch of pointers.

Community
  • 1
  • 1
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • The vertices array going away makes sense. So I'll try using std::vector for the model and see if the vertices are kept intact. Will also try declaring vertices on the heap properly as in the "returning a pointer to a local variable" link you included. Appreciated – user176692 Jan 19 '16 at 17:17
  • Keeping track of the pointers here through debugging their addresses. A lot of language concepts to iron out, but thanks for pointing out the scope problem. Separated the funcs for this work in progress, need to buy a book eventually so I stop unlearning malloc, memcpy, addressing principles. I dislike how I declared the vertices array, so will eventually read from file. – user176692 Jan 23 '16 at 20:15
1

you have to add to your struct Model an int to store the number of vertices and to take it into consideration across the rest of the program:

typedef struct Model{
   Vertex *vertices;
   int nVertices; // add this
} Model;

then you have to allocate in newModel() the memory for it like this:

model = (Model* )malloc(nVertices*sizeof(Vertex)+sizeof(int)); // this will allocate the necessary space 

(at that point, the number of vertices must be defined)

then use memset() to set to zero the allocated memory (if you need)
then add to setVertices(); a new int parameter to send the number of vertices and set the model->nVertices with it.

Claudiu
  • 91
  • 1
  • 1
  • The malloc style you used cleared up some sizing questions I had in the back of my head. Thanks. – user176692 Jan 19 '16 at 17:18
  • Got it running now. Not sure the best practice here, but going to stick with malloc'ing sizeof(Model) and malloc its members separately. Then I could use the Model, let its members be pointers, and malloc its vertices from other functions. This helped, so marking this answer 'up.' – user176692 Jan 23 '16 at 20:09