Marco
Marco

Reputation: 131

QToolBar children list always growing. Qt memory leak?

I would like to have only one QToolBar instance and modify it many times during the execution of my application. However, I'm concerned about the memory management done by Qt.

Consider the following:

QToolBar toolBar;
std::cout << toolBar.actions().size() << std::endl; // Prints 0
toolBar.addSeparator(); // will add an action
std::cout << toolBar.actions().size() << std::endl; // Prints 1
toolBar.clear();
std::cout << toolBar.actions().size() << std::endl; // Prints 0 again. Good!

Initially, the list of actions in a QToolBar is empty. Thus the first cout prints "0". An internal action is added to that list by "addSeparator". So the second cout prints "1". Finally, "clear", as expected, remove all actions and the last cout prints "0" again.

Now, consider what happens with the "children list":

QToolBar toolBar;
std::cout << toolBar.children().size() << std::endl; // Prints 3. Why?
toolBar.addSeparator(); // will add an action
std::cout << toolBar.children().size() << std::endl; // Prints 5. "addSeparator" has added two children.
toolBar.clear();
std::cout << toolBar.children().size() << std::endl; // Still prints 5. "Clear" did not remove any children!

Initially the children list has size 3. Then I call "addSeparator" and two guys are added to that list. Ok, I can live with that. However, after a call to "clear" these guys are not removed. For each "addSeparator" or "addWidget" call, two children are added and they are never removed.

I'm using Qt 5.4.1 for MSVC 2013, Windows.


Edit: Adding the code suggested by peppe. Please read the line comments.

QToolBar toolBar;
std::cout << toolBar.children().size() << std::endl; // Prints 3.
toolBar.addSeparator();
std::cout << toolBar.children().size() << std::endl; // Prints 5. "addSeparator" has added two children.

auto actions = toolBar.actions();

for (auto& a : actions) {
    delete a;
}

std::cout << toolBar.children().size() << std::endl; // Now this prints 4. Shouldn't be 3?

Upvotes: 0

Views: 436

Answers (1)

peppe
peppe

Reputation: 22734

Just take a look at the implementation of addSeparator:

QAction *QToolBar::addSeparator()
{
    QAction *action = new QAction(this);
    action->setSeparator(true);
    addAction(action);
    return action;
}

This creates a new child QAction and adds it to the widget's action list. clear clears the action list, but does not destroy the actions! Hence they'll still be around as children of the toolbar.

Qt doesn't know that you're not using those actions elsewhere -- they're meant to be used across multiple widgets. If you want to reclaim that memory, delete the action returned by addSeparator.

Upvotes: 2

Related Questions