Search code examples
c++sdlsdl-2

Multiply object is changed after changing one pointer


I'm just doing an Uni task which I though it's very simple. But I got stuck. The task is simple, it's just use SDL2 to make a input mapping system. I create a Button struct which has the name, rectangle and assigned key of the button.

vector<Button>buttons = {
     Button("up", SDL_Rect{ 100,100,100,20 },"Up"),
     Button("down", SDL_Rect{ 100,200,100,20 },"Down"),
     Button("left", SDL_Rect{ 100,300,100,20 },"Left"),
     Button("right", SDL_Rect{ 100,400,100,20 },"Right"),
     Button("reset", SDL_Rect{ 400,400,100,20 },"R")
};

Then when mouse is clicked and mouse position is inside one of the button it assign clickedButton pointer to this button.

if (evt.type == SDL_MOUSEBUTTONDOWN)
{   
    int x, y;
    SDL_GetMouseState(&x, &y);
    for (auto &b : buttons)
    {
        if (x > b.btn_rect.x && x<(b.btn_rect.x + b.btn_rect.w) && y > b.btn_rect.y && y < (b.btn_rect.y + b.btn_rect.h))
        {
            cout << "Button " << b.btn_name << " clicked" << endl;
            btClicked = &b;
            break;
        }
    }
}

Now here is the weird thing happened. When btClicked is not null I assign a key name to the this button. But every time I assign another button to btClicked the previous buttons assigned to btClicked will also change it's key name.

if (evt.type == SDL_KEYDOWN)
{
    if(btClicked!=NULL)
    {
        btClicked->assigned_key = SDL_GetKeyName(evt.key.keysym.sym);//breakpoint here
        btClicked = NULL;
    }

You can see the breakpoint debug below. All previous button those were assigned to btClicked are all changed. But btClicked is only point to one of the button. The breakpoint Debug

Anyone know what happening here? Please help.


Solution

  • The string pointed to by the return value of SDL_GetKeyName is only guaranteed valid until the next time SDL_GetKeyName is called. In this case, it looks like it has a static buffer that it re-uses for every call, so all of your Buttons end up pointing to the same string. This means you need to copy that string if you need it to remain valid for longer.

    The easiest way to achieve this would be to make your Button::assigned_key member a std::string instead of a raw const char*.

    This is almost always a good idea anyway, since keeping a const char* member in an object muddies ownership semantics and makes the application much more prone to this kind of error as well as memory leaks.