View previous topic :: View next topic |
Author |
Message |
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Sun Mar 10, 2013 3:52 am Post subject: Program organizattion question in c++ |
|
|
In the main function of my program, an instance of a certain kind calls one of it's methods.
In this method, another method from that instance is called, and from this second method a third one is also called. After two executions of the third function, I gather enough information from a file
to fill in a structure of certain kind. So far so good. This filling is done in the second method. After it's done, the structure is added to a vector container. Then the second method keep running a loop and gathering information to fill in another structures, and these keep being added to the vector.
The problem it is that I will need to use the information from these structures far ahead in the program execution, and soon the second method is over, these structures cease to exist, since they are declared locally and their scope has just ended. So I end with a vector full of garbage references.
So what is the best choice for a case like this? I can transfer part of the logic of these methods to the main function, so I will never run out of scope before the program finishes, but I really don't like this solution because: 1) Main is used basically as a collection of actions of several instances with very little logical in it. 2) The algorithm I created to extract information from a file is well organized being distributed in these three methods, a rewriting of it possibly is not going to be as elegant.
What I would really like would be to have something like vector that accepted pointers to dynamic memory, so the structures would keep existing after the method ended and them in the program end I would release the pointers stored in the hypothetical vector.
Any suggestions?
EDIT:
I experimented modifying the algorithm to run it partly in main and besides making the program uglier, it really doesn't solve my problem, since the structure is still being declared inside a loop, and when the loop finishes there will still be garbage in the vector.
Declaring structure variables outside the loop is not possible since I don't know how many I will need. What I really need is an vector that work with copies and not references. |
|
Back to top |
|
|
Hu Moderator
Joined: 06 Mar 2007 Posts: 21595
|
Posted: Sun Mar 10, 2013 4:45 am Post subject: |
|
|
You can use boost::ptr_vector for this purpose. You could also change the definition of the object being placed in the vector, so that it is self-contained. In my opinion, this is a good idea anyway. Most users would be surprised to find that they can insert an instance of your object into a vector and have the object become partially invalid while the vector is still valid. |
|
Back to top |
|
|
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Sun Mar 10, 2013 4:50 am Post subject: |
|
|
I will check boost::ptr_vector as soon as I have time.
What do you mean by "self-contained" exactly? You think it might be the best solution?
P:S: Check my edition of the first post |
|
Back to top |
|
|
Hu Moderator
Joined: 06 Mar 2007 Posts: 21595
|
Posted: Sun Mar 10, 2013 4:18 pm Post subject: |
|
|
I think you found a way to do something bad. Vectors do work with copies, not references. They copy whatever you give them, and maintain the copy for you. If you have managed to have stale data, that suggests you are forcing the vector to accept a reference instead. Perhaps you made a std::vector<T*> when you should have used a std::vector<T>.
By self-contained, I mean that a copy of your object should never become partially invalid as a result of local variables expiring. Your object should either embed or have a strong pointer to any resources it needs. You could mix these techniques if you have some sub-objects that are cheap to embed and others which ought to be on the heap.
Seeing a minimal sample of your code would help us help you. |
|
Back to top |
|
|
dmitchell Veteran
Joined: 17 May 2003 Posts: 1159 Location: Austin, Texas
|
Posted: Tue Mar 12, 2013 10:06 pm Post subject: Re: Program organizattion question in c++ |
|
|
One possibility is that the structure (struct) he mentions doesn't have a proper copy constructor and assignment operator. _________________ Your argument is invalid. |
|
Back to top |
|
|
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Wed Mar 13, 2013 6:33 am Post subject: |
|
|
Ok here are some code excerpts:
Code: | while (line != "") {
getline (fileReader,line);
if (line[0] != ' ')
continue;
getLineValue2 (lineNumbers, scene, lineNumbersIndex);
getLineValue2Counter++;
if (getLineValue2Counter==2) {
Material material;
getLineValue2Counter=0;
lineNumbersIndex=0;
material.color.red = lineNumbers[0];
material.color.green = lineNumbers[1];
material.color.blue = lineNumbers[2];
material.reflection = lineNumbers[3];
scene.addMaterial (material);
|
Code: | struct Material {
Color color;
float reflection;
}; |
Code: | inline void addMaterial (const Material &material) { materialContainer.push_back (material); } |
Code: | private:
std::vector <Material> materialContainer; |
Basically I don't know how many "material" structures I will find declared in the text file so I want to create it as needed, fill its members with the data from an array, data that I collect from a function, and then add it to the vector container that will exist until program termination |
|
Back to top |
|
|
Hu Moderator
Joined: 06 Mar 2007 Posts: 21595
|
Posted: Wed Mar 13, 2013 10:26 pm Post subject: |
|
|
I wanted you to provide us with enough code that we could reproduce the problem. The provided code is not even a full block, so we can only speculate on what your code does in the portions not shown. |
|
Back to top |
|
|
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Fri Mar 15, 2013 6:39 am Post subject: |
|
|
What parts shall I post? I thought the only relevant parts were these |
|
Back to top |
|
|
dmitchell Veteran
Joined: 17 May 2003 Posts: 1159 Location: Austin, Texas
|
Posted: Fri Mar 15, 2013 8:51 am Post subject: |
|
|
coltson: | while (line != "") {
getline (fileReader,line);
if (line[0] != ' ')
continue;
getLineValue2 (lineNumbers, scene, lineNumbersIndex);
getLineValue2Counter++;
if (getLineValue2Counter==2) {
Material material;
getLineValue2Counter=0;
lineNumbersIndex=0;
material.color.red = lineNumbers[0];
material.color.green = lineNumbers[1];
material.color.blue = lineNumbers[2];
material.reflection = lineNumbers[3];
scene.addMaterial (material);
|
The structure of this loop looks highly suspicious to me. My guess: the loop doesn't terminate when you think it does, and you end up with garbage in line and lineNumbers, resulting in garbage Material and the end of the vector. _________________ Your argument is invalid. |
|
Back to top |
|
|
Hu Moderator
Joined: 06 Mar 2007 Posts: 21595
|
Posted: Fri Mar 15, 2013 10:53 pm Post subject: |
|
|
coltson wrote: | What parts shall I post? I thought the only relevant parts were these | The portion you posted is not a valid C program. If I copy everything you posted into a file, give it a .c extension, and run gcc on it, I get compilation errors, because portions of the program are missing. |
|
Back to top |
|
|
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Sat Mar 16, 2013 7:02 pm Post subject: |
|
|
dmitchell wrote: |
The structure of this loop looks highly suspicious to me. My guess: the loop doesn't terminate when you think it does, and you end up with garbage in line and lineNumbers, resulting in garbage Material and the end of the vector. |
Well, your guess is wrong.
Quote: | The portion you posted is not a valid C program. If I copy everything you posted into a file, give it a .c extension, and run gcc on it, I get compilation errors, because portions of the program are missing. |
Well, full source is too big to put here, but something I can do is to make a new program copying only the relevant part into a single file. I will do that and post here |
|
Back to top |
|
|
dmitchell Veteran
Joined: 17 May 2003 Posts: 1159 Location: Austin, Texas
|
Posted: Sun Mar 17, 2013 9:22 am Post subject: |
|
|
coltson wrote: | Well, your guess is wrong. |
Very possible. What is the type of lineNumbers and material.color.red? _________________ Your argument is invalid. |
|
Back to top |
|
|
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Sat Mar 23, 2013 5:15 am Post subject: |
|
|
Quote: | Very possible. What is the type of lineNumbers and material.color.red |
float array and float.
I am with a bziped file with the code. There is a way to attach it to a message? |
|
Back to top |
|
|
dmitchell Veteran
Joined: 17 May 2003 Posts: 1159 Location: Austin, Texas
|
Posted: Sun Mar 24, 2013 4:09 am Post subject: |
|
|
coltson wrote: | I am with a bziped file with the code. There is a way to attach it to a message? |
I don't think so. Upload it somewhere (example) and post a link. _________________ Your argument is invalid. |
|
Back to top |
|
|
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Tue Mar 26, 2013 7:13 am Post subject: |
|
|
Ok, here is the file: http://ompldr.org/vaHZ4ag/test.tar.bz2
To run it, execute the file TEST, passing as parameter the file scene.ini.
To recompile it, save the content of the altered file and run test.sh
By default, It will print the content that was read from the file in the screen.
This is happening in the TextManager.cpp file, in the end of the getMaterialData method (the third method).
This is working as expected. However in the scanFile method (the first one), the one that calls getMaterialData, just after it's invocation, there is a lot of commented out cout's whose purpose is to show up the problem. These cout's are basically the same that press the vector content in the screen, running just after the last cout sequence with nothing between them. The only difference being that they are in a different method. If uncommented and the program gets recompiled, when the program runs again it will press: "segmentation fault" on the screen, like the content stored in vector run out of scope. |
|
Back to top |
|
|
dmitchell Veteran
Joined: 17 May 2003 Posts: 1159 Location: Austin, Texas
|
Posted: Tue Mar 26, 2013 3:47 pm Post subject: |
|
|
coltson wrote: | Ok, here is the file: http://ompldr.org/vaHZ4ag/test.tar.bz2
To run it, execute the file TEST, passing as parameter the file scene.ini.
To recompile it, save the content of the altered file and run test.sh
By default, It will print the content that was read from the file in the screen.
This is happening in the TextManager.cpp file, in the end of the getMaterialData method (the third method).
This is working as expected. However in the scanFile method (the first one), the one that calls getMaterialData, just after it's invocation, there is a lot of commented out cout's whose purpose is to show up the problem. These cout's are basically the same that press the vector content in the screen, running just after the last cout sequence with nothing between them. The only difference being that they are in a different method. If uncommented and the program gets recompiled, when the program runs again it will press: "segmentation fault" on the screen, like the content stored in vector run out of scope. |
You forgot to use braces. You have:
Code: | else if (line == "[Material]")
getMaterialData (scene);
cout << scene.materialContainer[0].color.red << endl;
...
cout << scene.materialContainer[2].reflection << endl; |
Only getMaterialData is executed conditionally. The cout statements are executed every iteration of the while loop, including before getMaterialData (after getImageData).
Also, instead of building up integers by reading one digit at a time from a string, I suggest you look at std::stringstream. _________________ Your argument is invalid. |
|
Back to top |
|
|
coltson n00b
Joined: 15 Oct 2005 Posts: 54
|
Posted: Fri Mar 29, 2013 6:37 am Post subject: |
|
|
Thanks.
When I was doing this part of the program, I read about stringstream and tested it, but since it converts the entire string it wasn't useful.
So I decided to write my own algorithm could be easier than search other functions that could help stringstream to accomplish my goals.
Now that I already did it, do you think it still worth to research that information ? |
|
Back to top |
|
|
dmitchell Veteran
Joined: 17 May 2003 Posts: 1159 Location: Austin, Texas
|
Posted: Fri Mar 29, 2013 4:47 pm Post subject: |
|
|
coltson wrote: | When I was doing this part of the program, I read about stringstream and tested it, but since it converts the entire string it wasn't useful.
So I decided to write my own algorithm could be easier than search other functions that could help stringstream to accomplish my goals.
Now that I already did it, do you think it still worth to research that information ? |
Yes, but not a high priority. Add it to your TODO file.
You might consider using the regular expression library, which would look something like this.
Code: | #include <regex>
#include <string>
#include <vector>
std::vector<float> getnumbers(std::string const& str)
{
static std::regex const numbers{"[+-]?(\\d*\\.)?\\d+"};
std::vector<float> result;
for (std::sregex_iterator it{str.begin(), str.end(), numbers}, end; it != end; ++it)
result.push_back(std::stof(it->str()));
return result;
} |
_________________ Your argument is invalid. |
|
Back to top |
|
|
|