Sign in to follow this  
Stoic

std::vector issue

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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];
};


Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this