Public Group

# SFML Pointer to Pointer

This topic is 2594 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## 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:

 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; } 

Maps:

 std::map< std::string, sf::String* > RenderStrings; std::map< std::string, sf::Font** > RenderFontPointers; 
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 on other sites
What is the 'crash'? What is the debugger telling you is wrong?

##### Share on other sites

What is the 'crash'? What is the debugger telling you is wrong?

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 on other sites

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:
 RenderFontPointers[ MediaDIR ] = &fontFile; 

##### Share on other sites
Thanks so much. It works now, along with the debugging!

##### 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 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.

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:
 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 ); } } 
GetFont() returns a reference (&).

Created like so:
 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; } 

Sorry for the multiple code dumps.

##### 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:
 class TextRenderer { public: // ... private: struct FontData { sf::Font *font; std::map<std::string, sf::String *> stringCache }; map<std::string, std::shared_ptr<FontData> > FontMap; }; 
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.

1. 1
2. 2
3. 3
4. 4
Rutin
18
5. 5

• 11
• 21
• 12
• 11
• 11
• ### Forum Statistics

• Total Topics
631405
• Total Posts
2999888
×