Vector problem

Reply

Join Date: Sep 2007
Posts: 35
Reputation: Evan M is an unknown quantity at this point 
Solved Threads: 4
Evan M's Avatar
Evan M Evan M is offline Offline
Light Poster

Vector problem

 
0
  #1
Oct 9th, 2008
I have a vector array of a class that's giving me some crap. I would beat it up, but that might result in some innocent circuits getting damaged.

Class:
  1. class Font {
  2. public:
  3. Font();
  4. ~Font();
  5.  
  6. int style;
  7. int ptSize;
  8. std::string name;
  9. TTF_Font *font;
  10. };
  11.  
  12. Font::Font()
  13. {
  14. style = TTF_STYLE_NORMAL;
  15. ptSize = 0;
  16. name = "";
  17. font = NULL;
  18. }
  19.  
  20. Font::~Font()
  21. {
  22. // Access violation
  23. TTF_CloseFont( font );
  24. }

Code:
  1. std::vector<Font> fonts;
  2.  
  3. SDL_Surface *renderText( std::string fontName, int ptSize, std::string text, const SDL_Color *textColor, const SDL_Color *backroundColor, int flags )
  4. {
  5. // cut
  6.  
  7. if( fontElement == -1 ) {
  8. std::string fileName = "c:\\windows\\fonts\\" + fontName;
  9.  
  10. // class constructor called here
  11. fonts.resize( fonts.size() + 1 );
  12. fontElement = fonts.size() - 1;
  13. fonts[ fontElement ].ptSize = ptSize;
  14. fonts[ fontElement ].name = fontName;
  15. fonts[ fontElement ].font = TTF_OpenFont( fileName.c_str(), ptSize );
  16. if( fonts[ fontElement ].font == NULL ) {
  17. return NULL;
  18. }
  19.  
  20. if( fontStyle != TTF_STYLE_NORMAL ) {
  21. fonts[ fontElement ].style = fontStyle;
  22. TTF_SetFontStyle( fonts[ fontElement ].font, fontStyle );
  23. }
  24. // class destructor called here
  25. }
  26.  
  27. // cut
  28.  
  29. // no error here
  30. if( flags & FH_BLENDED ) {
  31. return TTF_RenderText_Blended( fonts[ fontElement ].font, text.c_str(), fgColor );
  32. }
  33. else if( flags & FH_SHADED ) {
  34. return TTF_RenderText_Shaded( fonts[ fontElement ].font, text.c_str(), fgColor, bgColor );
  35. }
  36. else if( flags & FH_SOLID ) {
  37. return TTF_RenderText_Solid( fonts[ fontElement ].font, text.c_str(), fgColor );
  38. }
  39.  
  40. return NULL;
  41. }

The problem is that right after the if statement the class destructor is called. Oddly enough, when I use fonts[].font later, I don't get an error; I only get the access error after the program attempts to terminate, because it calls the destructor again. It goes something like this:

constructor
loads font
destructor
renders text - renders with a closed font??
back to main
display text - displays fine
destructor - error happens here

I can post the rest of the source code, if necessary. What stupid thing am I missing?
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 305
Reputation: stilllearning has a spectacular aura about stilllearning has a spectacular aura about 
Solved Threads: 43
stilllearning stilllearning is offline Offline
Posting Whiz

Re: Vector problem

 
0
  #2
Oct 9th, 2008
This is interesting. I have never really tried to insert elements into a vector in this fashion. I normally use the push_back() function to add values to the vector. I attempted to do what you are doing, and calling the resize() function calls the class constructor once and the destructor twice. And then the destructor is called once more when the main exits. Which would be very bad if you were using dynamically allocated elements in your class. I am not sure how this works internally, but is there a reason why you are using this logic instead of just adding elements to the vector using push_back() ?

  1. class myClass{
  2. public:
  3. myClass(){cout << "myclass constructor" << endl;}
  4. ~myClass(){cout << "myclass destructor" << endl;}
  5. int number;
  6. };
  7.  
  8. int main ()
  9. {
  10. vector<myClass> myVector;
  11. int element;
  12.  
  13. myVector.resize(myVector.size() + 1);
  14. element = myVector.size() - 1;
  15. myVector[element].number = 100;
  16. myVector[element].number = 200;
  17.  
  18. return 0;
  19. }
Last edited by stilllearning; Oct 9th, 2008 at 8:19 pm.
Reply With Quote Quick reply to this message  
Join Date: Sep 2007
Posts: 35
Reputation: Evan M is an unknown quantity at this point 
Solved Threads: 4
Evan M's Avatar
Evan M Evan M is offline Offline
Light Poster

Re: Vector problem

 
0
  #3
Oct 9th, 2008
I used resize instead of push_back because push_back requires that you put in a value. If I were to declare another instance of Font, set all the variables, then use that in push_back(), it is my understanding that the pointers from both instances would point to the same object. Since the temporary class would call the destructor at the end of the if statement it would delete the object, leaving me with a dangling pointer. Alternatively, I could do:
  1. Font temp;
  2. fonts.push_back( temp );
It does work, but it just seems odd. Of course, I could be wrong cause I'm no expert on vector arrays.
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 305
Reputation: stilllearning has a spectacular aura about stilllearning has a spectacular aura about 
Solved Threads: 43
stilllearning stilllearning is offline Offline
Posting Whiz

Re: Vector problem

 
0
  #4
Oct 9th, 2008
If you wanted to you could use a vector of pointers instead of objects. That way you can create a new object as you needed it and add it to your vector. And then delete them all at the end.

  1. vector<myClass*> myVector;
  2. myClass *tmp;
  3.  
  4. for(unsigned int i = 0; i < 5; i++){
  5. tmp = new myClass(i);
  6. myVector.push_back(tmp);
  7. }
  8.  
  9. // do stuff
  10.  
  11. // delete any allocated pointers
  12. for (unsigned int i = 0; i < myVector.size(); i++){
  13. delete myVector[i];
  14. }
Last edited by stilllearning; Oct 9th, 2008 at 9:12 pm.
Reply With Quote Quick reply to this message  
Join Date: Sep 2007
Posts: 35
Reputation: Evan M is an unknown quantity at this point 
Solved Threads: 4
Evan M's Avatar
Evan M Evan M is offline Offline
Light Poster

Re: Vector problem

 
0
  #5
Oct 9th, 2008
The problem with that approach is how my function works. Each time the program needs to display text, it calls renderText(). Loading a font takes my computer about 3 milliseconds, and I'm already worried about SDL going too slow. Thus, I opted to use a vector array of class 'Font', since vectors are easiest when it comes to expanding arrays, and each class can automatically close the TTF_Font* variable, plus I can use previously loaded fonts and I could do it all without the hassle of dynamic memory. Since no other function has access to the vector, I can't delete the class pointers in the vector at the end of the program.

Your response did get me thinking about some possible alternatives. I could make another flag to put in the flags parameter that would let the function know it has to delete the fonts; I could make a class which would contain the vector of pointers to the 'Font' class, making use of the class destructor to delete the vector; or I could give a void function access to the vector, so I could use atexit() to delete the vector (probably wouldn't work as the vector would probably be removed from memory prior to the atexit() call).

If you have any other ideas, please let me know, as mine kinda suck. I would still like to know why the vector is acting as it is, so I can avoid this in the future.
Reply With Quote Quick reply to this message  
Join Date: Sep 2007
Posts: 35
Reputation: Evan M is an unknown quantity at this point 
Solved Threads: 4
Evan M's Avatar
Evan M Evan M is offline Offline
Light Poster

Re: Vector problem

 
0
  #6
Oct 11th, 2008
Well, I messed around with my code for a few hours, and I discovered that it wasn't actually a problem with the vector (as always, I blamed the other code first). The problem is by the time the program gets to the Font destructor, the TTF library has already quit. This is really quite annoying, since I closed the TTF library using atexit().

The problem now is getting the class destructor to run before the atexit stuff. With the code:
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. class myClass {
  6. public:
  7. myClass() { cout << "Constructor" << endl; }
  8. ~myClass() { cout << "Destructor" << endl; }
  9. };
  10.  
  11. myClass loser;
  12.  
  13. void func()
  14. {
  15. cout << "Func" << endl;
  16. }
  17.  
  18. int main()
  19. {
  20. atexit( func );
  21. return 1;
  22. }
the output will be "Constructor Func Destructor". Does anybody know a [non-messy] way around this?
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC