1

I have found nerve wracking issue which I seem to be unable to solve.

SceneSettings::SceneSettings()
{
    unsigned int w = (ConfigurationManager::GetInstance().GetWidth() >> 1) - 80;
    unsigned int h = (ConfigurationManager::GetInstance().GetHeight() >> 1) - 50;

    std::vector< std::string > menu_items;

    menu_items.push_back("Graphic Settings");
    menu_items.push_back("Sound Settings");
    menu_items.push_back("Game Settings");
    menu_items.push_back("Back");

    Label* aux = NULL;
    for ( unsigned int i = 0; i < menu_items.size(); i++ )
    {
        aux = new Label(menu_items[i], w, h);
        items.push_back(aux);
        aux = NULL;

        aux = new Label(menu_items[i], w, h);
        aux->SetColor(255, 0, 0);

        hover_section.push_back(aux);
        hover.push_back(false);

        aux = NULL;
        h += 25;
    }
}

SceneSettings::~SceneSettings()
{
    for (unsigned int i = 0; i < items.size(); i++)
    {
        delete items[i];
        delete hover_section[i];
    }

    items.clear();
    hover_section.clear();
}

void SceneSettings::Draw()
{
    for ( unsigned int i = 0; i < items.size(); i++ )
    {
        if (hover[i])
            hover_section[i]->Draw();
        else
            items[i]->Draw();
    }
}

void SceneSettings::HandleEvents(SDL_Event& event)
{
    switch(event.type)
    {
        case SDL_MOUSEMOTION :
        {
            int x = event.motion.x;
            int y = event.motion.y;

            for ( unsigned int i = 0; i < items.size(); i++ )
                hover[i] = items[i]->GetIsInLabel(x, y);
        } break;
    }
}

Now what it does is, that first label "Graphic Settings" is not displayed. (not invisible, just plainly not visible)

items are defined as:

std::vector< Label* > items;
std::vector< Label* > hover_section;
std::vector< bool > hover;

For some reason it doesnt work, however in another scene ("main_menu") I have identical vector of labels (only captions are different) which works ok.

Now this one is more interesting that it seems. Since not only does it not display first item, but it displays 1st hover item even if mouse is completely out its range.

If I replace std::vector for direct Label* menu_item_1 in SceneSettings header, it displays correctly. Which leads me to think its connected to std::vector

One more thing I don't quite understand is, that if I run it in debug mode and going by steps, it displays correctly, however neither watches nor call stack does show anything unusual.

Any help is appreciated.

8
  • 2
    To save you nervs, I urgently recommend you using smart pointers instead of raw pointers stored in your vector: en.cppreference.com/w/cpp/memory Commented Sep 13, 2015 at 12:10
  • I could try that, but that still wouldn't tell me what is wrong with my code here. Commented Sep 13, 2015 at 12:12
  • Well not really enough context or test case to diagnose, but I'd suspect you got something wrong with The Rule of Three. Commented Sep 13, 2015 at 12:14
  • If something tends to work when running in a debugger, but not when running outside of the debugger, it's usually an indicator that you use uninitialized data. Debuggers usually clears all memory, meaning that all pointers will be null-pointers. If you check for null-pointers the code will work, but uninitialized data is indeterminate and will be seemingly random and most likely not null, so the null-pointer check thinks that the uninitialized pointer is not null, leading to undefined behavior. Commented Sep 13, 2015 at 12:14
  • By the way, is your program multi-threaded? Do multiple threads access the data? And indeed, do you follow the rules of three/five/zero? And do you really need to use pointers? Commented Sep 13, 2015 at 12:21

2 Answers 2

1

If you are passing SceneSettings objects by value anywhere, either as arguments to functions or returning such objects, then you definitely need to consider your use of pointers in the vectors, or have to implement a copy-constructor and a copy-assignment operator (as told by the rule of three).

The default functions created by the compiler will only do shallow copying, i.e. it copies the vectors and the pointers, it doesn't create new pointers (deep copying). That leads to you having two objects both containing pointers to the same objects in the vectors, and if one object is destructed if will free the memory, leaving the other object with stray pointers and that will lead to undefined behavior.

Sign up to request clarification or add additional context in comments.

2 Comments

I will try to implement it and hopefully it will resolve the issue.
While it wasn't answer I found your reply very insightful and will definitely start upholding rule of three and using smart pointers. Thank you for your time.
1

It turns out the problem was in Label class, in which I neglected to initialize texture and buffer ids for GLSL. Adding initial values (0) to them in Label constructor fixed the problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.