Sign in to follow this  
Drakk

SFML Pointer to Pointer

Recommended Posts

Hello, I have this function which creates SFML Strings / Fonts. But I want to refuse some of the already created fonts (if we load the same font file).
I have two std maps, seen here:

[code]
sf::String *CRenderManager::CreateFontString( const std::string &text, const std::string &fontFilename, float PosX, float PosY )
{
char MediaDIR[256];
sprintf_s( MediaDIR, 255, "media/%s", fontFilename.c_str() );

// [TJ]:
// Always alloc for a string, we check the map if we already have this font loaded
// so we don't need to use more memory (allocating sf::font)
sf::String *string = new sf::String;
sf::Font *fontFile = NULL;

std::map<std::string, sf::Font**>::iterator it = RenderFontPointers.find( MediaDIR );

if( it != RenderFontPointers.end() )
{
string->SetFont( **it->second );
}
else
{
sf::Font *fontFile = new sf::Font;
if( fontFile->LoadFromFile( MediaDIR ) )
{
string->SetFont( *(fontFile) );
RenderFontPointers[ MediaDIR ] = &fontFile;
}
}

RenderStrings[ text ] = string;
string->SetPosition( PosX, PosY );
string->SetText( text );

return string;
}
[/code]

Maps:

[code]
std::map< std::string, sf::String* > RenderStrings;
std::map< std::string, sf::Font** > RenderFontPointers;
[/code]
This code crashes when ran. It's use "RenderFontPointers" which is the problem. I'm sure there's a better way, I have a pointer->pointer->sf::font so I can reuse it. Any idea why it just crashes? Or is there a better way todo this? Sorry if it's to little code. Thanks!

Share this post


Link to post
Share on other sites
[quote name='phantom' timestamp='1305497299' post='4811227']
What is the 'crash'? What is the debugger telling you is wrong?
[/quote]

Unfortunate, because of the way the debugger loads the .exe (i think?) it doesn't find my resources (.bmp .wav etc) so I have to run it outside the IDE,
or SFML dumps all kinds of "can't find file <file>" errors.

Share this post


Link to post
Share on other sites
[quote]
Unfortunate, because of the way the debugger loads the .exe (i think?) it doesn't find my resources (.bmp .wav etc) so I have to run it outside the IDE...
[/quote]
You just need to correct your working directory (which you can set in the IDE perferences), or don't use absolute paths.

As for your actual problems, you are storing a pointer to a local variable inside your map. Instead, don't store double pointers in the map, store regular pointers (or even smart pointers).

Offending line:
[code]
RenderFontPointers[ MediaDIR ] = &fontFile;
[/code]

Share this post


Link to post
Share on other sites
[s]Because fontFile is just a local variable inside the else block. Once you exit the block, it doesn't exist anymore.

The font you have allocated on the heap still exists, but the particular 4 bytes you were using to hold the value of the pointer has been erased.[/s]

Bah, you edited out your question. Anyway I'll leave this in case the answer helps you.

Share this post


Link to post
Share on other sites
[quote name='karwosts' timestamp='1305499259' post='4811246']
[s]Because fontFile is just a local variable inside the else block. Once you exit the block, it doesn't exist anymore.

The font you have allocated on the heap still exists, but the particular 4 bytes you were using to hold the value of the pointer has been erased.[/s]

Bah, you edited out your question. Anyway I'll leave this in case the answer helps you.
[/quote]

Yeah. I didn't look hard enough before I posted. But i've ran into one last issue.
How can I "deallocate" memory via reference?

Removed like so:
[code]
void CRenderManager::ClearFontString( const std::string &text )
{
std::map<std::string, sf::String*>::iterator it = RenderStrings.find( text );
if( it != RenderStrings.end() )
{
delete it->second->GetFont();
delete it->second;

RenderStrings.erase( it );
}
}
[/code]
GetFont() returns a reference (&).

Created like so:
[code]
sf::String *CRenderManager::CreateFontString( const std::string &text, const std::string &fontFilename, float PosX, float PosY )
{
char MediaDIR[256];
sprintf_s( MediaDIR, 255, "media/%s", fontFilename.c_str() );

// [TJ]:
// Always alloc for a string, we check the map if we already have this font loaded
// so we don't need to use more memory (allocating sf::font)
sf::String *string = new sf::String;
sf::Font *fontFile = NULL;

std::map<std::string, sf::Font*>::iterator it = RenderFontPointers.find( MediaDIR );

if( it != RenderFontPointers.end() )
{
string->SetFont( *(it->second) );
}
else
{
sf::Font *fontFile = new sf::Font;
if( fontFile->LoadFromFile( MediaDIR ) )
{
string->SetFont( *(fontFile) );
RenderFontPointers[ MediaDIR ] = fontFile;
}
}

RenderStrings[ text ] = string;

string->SetPosition( PosX, PosY );
string->SetText( text );

return string;
}
[/code]

Sorry for the multiple code dumps.

Share this post


Link to post
Share on other sites
Don't delete the font when removing a string, the font appears to be shared by multiple sf::String instances. However, You must delete the fonts in your destructor.

Also, CreateFontString could overwrite an existing entry in the map, even one that has a different font! I don't know why you are storing the strings in a map at all, the main reason to do so would be to cache duplicate strings, but you don't appear to be doing this. If you do want to cache repeated strings, I'd recommend restructuring your code like so:
[code]
class TextRenderer
{
public:

// ...

private:
struct FontData
{
sf::Font *font;
std::map<std::string, sf::String *> stringCache
};

map<std::string, std::shared_ptr<FontData> > FontMap;
};
[/code]
Be very careful if you do decide to go down this route though, what happens if you end up trying to render the same string in two locations? I would probably just use a font cache for the moment, and only add a cache for the strings later on if this proves necessary.

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