-
Hello guys,
I have a problem with my sf::Sprite in my own class(CEditbox).
I figured out that as soon as i use any command with my variable 'text' of sf::Text the sprite's sf::Drawable and sf::Transformable property '__vfptr' turns 'unable to read memory'. Every other property remains fine.
Therefore i get the following error, if i try to draw the sprite:
Unhandled exception at 0x0F134CBE (sfml-graphics-d-2.dll) in Editor.exe: 0xC0000005: Access violation reading location 0x00000004.
This is the class, where the editboxes are stored:
class CControls{
public:
CControls(sf::RenderWindow& paWindow, CAssetmanager& paAm);
~CControls(void);
void addEditbox(int paType, sf::Vector2i paPos);
private:
std::vector<std::shared_ptr<CEditbox>> editboxes;
sf::RenderWindow& window;
CAssetmanager& am;
};
CControls::CControls(sf::RenderWindow& paWindow, CAssetmanager& paAm) : window(paWindow), am(paAm) {
}
CControls::~CControls(void){
}
void CControls::addEditbox(int paType, sf::Vector2i paPos){
editboxes.push_back(std::shared_ptr<CEditbox>(new CEditbox(paType, paPos, window, am)));
}
This is the class itself:
class CEditbox {
public:
CEditbox(int paType, sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm);
~CEditbox(void);
void setText(std::string paText);
private:
sf::Font& font;
sf::Text text;
sf::RenderWindow& window;
CAssetmanager& am;
};
CEditbox::CEditbox(int paType, sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm) : window(paWindow), font(paAm.getFont()), am(paAm),line(sf::RectangleShape(sf::Vector2f(2, 20))){
switch(paType){//templates for editboxes
case 1:
sprite.setTexture(paAm.getTexture(2));
sprite.setTextureRect(paAm.getTextureRect(209));
text.setFont(font);
text.setCharacterSize(20);
text.setPosition(paPos.x + 5, paPos.y + 5);
text.setColor(sf::Color::Black);
break;
}
text.setString(sf::String(""));
sprite.setPosition(pos.x, pos.y);
size = sf::Vector2i(sprite.getTextureRect().width, sprite.getTextureRect().height);
}
CEditbox::~CEditbox(void){
}
void CEditbox::setText(std::string paText){
text.setString(paText);
}
I showed only the most important parts of the code (to my mind). If i completly comment all 'text' commands out, everything works fine.
What could be the problem?
Im using MVS2012 and the dynamic version of sfml.
edit:completly modified
-
Check this (http://en.sfml-dev.org/forums/index.php?topic=5559.0)
-
If the post still not goes by with the forum's rules please let me know or any further improvements should be made. This issue really drives me crazy :-[
-
0x00000004 means that the address of the class you're using is probably 0x00000000. This means that you're using a pointer and that you forgot to initialise this!
Look where you're using the instance CEditBox, check if it is using -> and that new is added.
This is probably what you're dealing withCEditBox *t_EditBox;
t_EditBox->DoSomethingWithText();
This is what it needs to becomeCEditBox *t_EditBox = new CEditBox();
t_EditBox->DoSomethingWithText();
//.. And when you're done using this editbox..
delete t_EditBox;
Or simply:CEditBox t_EditBox = CEditBox();
t_EditBox.DoSomethingWithText();
Then deleting will be handled for you when you leave the scope
-
Hello Holland, thank you for your reply.
Im currently using your advice in a slightly other way (smartpointer on a new object instance):
editboxes.push_back(std::shared_ptr<CEditbox>(new CEditbox(paType, paPos, window, am)));
I can do anything with my editbox-object such as 'setText', 'isActiv' or anything else, but my sprite variable gets corrupted on it's __vfptr property (all other properties like texture or the position is just fine!), therefore the pointer should be initialised correctly.
A simple assignment will fail due it's missing '=' operator.
edit: I already tried unique_ptr and raw pointers, but the issue remains.
-
...
This is what it needs to becomeCEditBox *t_EditBox = new CEditBox();
t_EditBox->DoSomethingWithText();
//.. And when you're done using this editbox..
delete t_EditBox;
Manual memory management - eeek. :-(
Use std::unique_ptr / std::make_unique .
RAII is a good thing.
If I see "delete foo" or "delete[] foo" in modern C++, I'm instantly thinking "you're doing it wrong"..
-
Guys, i tried somethin new.
I replaced my text variable with a unique_ptr. This solves the sprite issue! But now I got another one, somethings really bad in this code.
The problem is, i can't set a font to my text. The font is managed in the assetmanager and is valid. I have no problems using the font on other objects. I checked my font variable which is of type sf::Font& and it is valid the whole time, but if I try to set the font to my text, the properties of font remain "unable to read memory"
This is my code now:
class CEditbox {
public:
CEditbox(int paType, sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm); ~CEditbox(void);
private:
sf::Font& font;
std::unique_ptr<sf::Text> text;
sf::RenderWindow& window;
CAssetmanager& am;
};
CEditbox::CEditbox(int paType, sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm) : window(paWindow), font(paAm.getFont()), am(paAm),line(sf::RectangleShape(sf::Vector2f(2, 20))){
active = false;
visible = false;
pos = paPos;
std::unique_ptr<sf::Text> text(new sf::Text("ok", font, 20));
(*text).setFont(paAm.getFont());
sf::Text text2 = sf::Text("ok", font, 20);
switch(paType){//templates for editboxes
case 1:
(*text).setFont(font);
(*text).setCharacterSize(20);
(*text).setPosition(paPos.x + 5, paPos.y + 5);
(*text).setColor(sf::Color::Black);
break;
}
(*text).setString(sf::String(""));
}
Those lines before the switch statement are there for test purpose. The issue occurs on both, on the smartpointer variable text and the normal object text2, i cannot set the font to them. But the font isn't deleted and the address in my font variable is valid! All other properties of the text variables are valid too.
Thank you for your help and patience.
-
Have a look at this articel: http://en.wikipedia.org/wiki/Variable_shadowing
You are creating a "new" local variable "text" in your constructor instead of modifying the member variable. To avoid this issue in the future I suggest you to use a prefix for member variables, for example mText/m_text...
And learn to interpret errors of your compiler/debugger/OS. If you get "unable to read memory" from a pointer check if its not "nullptr" or pointing to an not existing object (not possible with smartpointer but with normal pointers/ref)
AlexAUT
-
Hello Alex,
I read your article and tried other names for the affecting variables. This is not the problem, the issue remains :( This is the code i have changed.
CEditbox::CEditbox(int paType, sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm) : window(paWindow), mFont(paAm.getFont()), am(paAm),line(sf::RectangleShape(sf::Vector2f(2, 20))){
std::unique_ptr<sf::Text> mText(new sf::Text("ok", mFont, 20));
switch(paType){//templates for editboxes
case 1:
(*mText).setFont(mFont);
(*mText).setCharacterSize(20);
(*mText).setPosition(paPos.x + 5, paPos.y + 5);
(*mText).setColor(sf::Color::Black);
}
(*mText).setString(sf::String(""));
}
I have to create the 'new' variable, otherwise mText would be a nullptr, i tried it. Because there is no existing instance of a variable text.
I know that a "unable to read memory" error will most times be a nullptr issue. but mFont is no nullptr. I even compared the address of the mFont variable with my address in the assetmanger class and it is the same. This font is used by other controls like buttons and works perfectly.
Thank you for your answer, maybe you have some more suggestions? Or did I misunderstood something?
-
No I meant you are creating a local variable with this line which shadows the member variable:
std::unique_ptr<sf::Text> mText(new sf::Text("ok", mFont, 20));
This line should be
mText = std::unique_ptr<sf::Text>(new sf::Text("ok", mFont, 20)); //std::make_unique if supported by your compiler (c++14)
or use it in the initializer list of the constructor:
mText(new sf::Text("ok", mFont, 20))
AlexAUT
-
Thank you for the quick answer.
I replaced the affecting line with your suggestion:
mText = std::unique_ptr<sf::Text>(new sf::Text("ok", mFont, 20));
but the issue remains :(
mText has the right charsize and the right string "ok", but the font is still unreadable. And i'm sure mFont is valid, because im using it in another class, where everything works fine.