std::vector issue

Started by
6 comments, last by Sneftel 17 years, 6 months ago
Hi all - I'm working on a font system for my engine, and I've run into a strange constructor issue with std::vector. It occurs to me that I'm doing some rather complicated stuff here, but I don't think I'm doing anything "illegal." Can someone give me a push in the right direction? Here's a slice of my code -

class BitmapFont
{
    struct FontChar
    {
        FontChar(): x(0),y(0),Width(0),Height(0),XOffset(0),YOffset(0),XAdvance(0),Page(0)
        {}

        uint16 x, y;             // represent pixel coords in the texture
        uint16 Width, Height;    // of the char in the texture
        int16  XOffset, YOffset; // for the desitnation rect
        uint16 XAdvance;         // for rendering
        uint16 Page;             // Unused for now (only support 1 page fonts)

        //Pairs for which I am the SECOND character. - makes iteration easier
        std::vector<KerningPair> KPairs; 
    };

    FontChar chars[256];
};

I'm getting a crash when it tries to initialize a FontChar in the BitmapFont constructor. Specifically, it's crashing in the "Buy" method for the "KPairs" vector, telling me that there's a corrupt block somewhere. I'm using VS 2003, and I know that Visual Studio historically has problems with their STL implementations, but it's also possible that I'm screwing something up here. Can anyone see anything wrong? Thanks for the help!
...
Advertisement
Need more code!

My guess is that the problm is in your KerningPair class, probably in its constructor, copy constructor or destructor. If you could post that class it might help.
Hmm, ok. The KerningPair class is actually really simple. I doubt it could be the problem, but I added it in the same place it is in my code.

class BitmapFont{    //These will be created on demand, so we don't really need to initialize them    struct KerningPair    {        uint8 first;        uint8 second;        int8 dist;    };    struct FontChar    {        FontChar(): x(0),y(0),Width(0),Height(0),XOffset(0),YOffset(0),XAdvance(0),Page(0)        {}        uint16 x, y;             // represent pixel coords in the texture        uint16 Width, Height;    // of the char in the texture        int16  XOffset, YOffset; // for the desitnation rect        uint16 XAdvance;         // for rendering        uint16 Page;             // Unused for now (only support 1 page fonts)        //Pairs for which I am the SECOND character. - makes iteration easier        std::vector<KerningPair> KPairs;     };    FontChar chars[256];};

...
Quote:Original post by Stoic
Hmm, ok. The KerningPair class is actually really simple. I doubt it could be the problem, but I added it in the same place it is in my code.

*** Source Snippet Removed ***


No, that seems to be fine. I cant see how that ( anypart of your code ) could possibly fail.

Is there more code in the other classes, like BitmapFont? How are you creating the bitmap font objects, in an array or vector too?
Unless I'm missing something obvious, I don't think there's enough information there to guess at the cause of the problem. You mentioned a 'Buy' method - what's that exactly? Anyway, perhaps you could post some of the code where you actually initialize the FontChar's and/or manipulate the vector itself.
Dude, you haven't posted a single line of code which is actually executed... just data structures (which look fine). How are we supposed to know what's wrong?
Sneftel -

Sorry about that. The truth is, the code is failing in the BitmapFont constructor, which actually is executed. It doesn't have any custom code (the blank curly braces after the definition). 256 FontChars are created when the BitmapFont is created, they fill in the static array.

class BitmapFont{    BitmapFont(): LineHeight(0), Base(0), TextureW(0), TextureH(0), numPages(1) {}    ~BitmapFont() {}    struct FontChar    {        FontChar(): x(0),y(0),Width(0),Height(0),XOffset(0),YOffset(0),XAdvance(0),Page(0)        {}        uint16 x, y;             // represent pixel coords in the texture        uint16 Width, Height;    // of the char in the texture        int16  XOffset, YOffset; // for the desitnation rect        uint16 XAdvance;         // for rendering        uint16 Page;             // Unused for now (only support 1 page fonts)        //Pairs for which I am the SECOND character. - makes iteration easier        std::vector<KerningPair> KPairs;     };    FontChar chars[256];    bool LoadFromFiles(std::string Descriptor_fname, std::string Texture_fname)    {        //Edit in the alredy existing "chars" array with information from the file        //  for example -> chars['s'].x = 120;        //Load the Texture    }    void PrintString(std::string s, const Vector2D &Pos);    FontChar chars[256];    uint16 LineHeight;    uint16 Base;    uint16 TextureW;    uint16 TextureH;    uint16 numPages;    CGfxTexture *FontTexture;};


I just create a bitmap font as a member variable of my application class.

class ApplicationState{    ProtoState() {}    bool Init()    {   //...  all kinds of other application stuff        testFont.LoadFromFiles("test.fnt", "test_00.tga");    }    void Render()    {        testFont.drawString("Hello, World!", Vector2D(100,100));    }private:    BitmapFont testFont;};


The ApplicationState data structure is created dynamically before the gameloop starts. Since the BitmapFont is a member of the ApplicationState, it gets created statically at the same time, which is when the empty constructor is created.

Hope that's enough info. I'm going to try and do a full rebuild in case it's just Visual Studio acting weird....

jyk - "Buy" is a member function of Vector (where I believe it does dynamic allocation)

In <vector>
	vector()		: _Mybase()		{	// construct empty vector		_Buy(0);  //this is where I crash		}protected:	bool _Buy(size_type _Capacity)		{	// allocate array with _Capacity elements		_Myfirst = 0, _Mylast = 0, _Myend = 0;		if (_Capacity == 0)			return (false);		else if (max_size() < _Capacity)			_Xlen();	// result too long		else			{	// nonempty array, allocate storage			_Myfirst = this->_Alval.allocate(_Capacity);			_Mylast = _Myfirst;			_Myend = _Myfirst + _Capacity;			}		return (true);		}


The thing that gets me, is that the vector shouldn't need to allocate anything until I add KerningPairs to the FontChars (which I haven't tried to do yet). That happens in LoadFromFiles(). I figured that the vectors had some static information, which would include a pointer to any storage that wouldn't be allocated until after I tried to push something into it.

Until this point, all memory allocation for this class has been static default allocation.


The reason that I've been so sparse with my code is because the vast majority of it hasn't been called by the time the crash happens.

Sorry for the trouble!
...
Stuff looks fine there. If it is memory corruption, though, the base cause is likely to be earlier in your program.

Comment out everything in your main() function, and just create a new BitmapFont. If that works, your problem lies outside the class, and in the stuff that happens before ApplicationState is ever created.

This topic is closed to new replies.

Advertisement