Qt-interest Archive, December 2006
Qt application crashes in valgrind
Message 1 in thread
My program crashes when run in valgrind, but not otherwise:
$ valgrind --tool=massif ./foo.dbg
==11163== Massif, a space profiler.
==11163== Copyright (C) 2003, Nicholas Nethercote
==11163== Using LibVEX rev 1658, a library for dynamic binary translation.
==11163== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==11163== Using valgrind-3.2.1-Debian, a dynamic binary instrumentation
framework.
==11163== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==11163== For more details, rerun with: -v
==11163==
==11163==
==11163== Process terminating with default action of signal 11 (SIGSEGV)
==11163== Access not within mapped region at address 0x8
==11163== at 0x54BC9EB: QAction::setChecked(bool) (qaction.h:46)
==11163== by 0x40F3D7: Foo::slot_foo(QAction*) (foo.cc:303)
[...]
==11163== by 0x40DAF2: main (main.cc:31)
==11163==
==11163== Total spacetime: 2,124,847,907 ms.B
==11163== heap: 96.5%
==11163== heap admin: 2.4%
==11163== stack(s): 0.9%
It seems this happens in QAction, but I checked with gdb, the pointers are
all valid. The slot_foo gets called by a selection in a popup menu. I am
really at the end of my wits here, since the program really seems to be
fine. What else could cause this?
Arne
--
[ signature omitted ]
Message 2 in thread
Arne Schmitz wrote:
> My program crashes when run in valgrind, but not otherwise:
>
> It seems this happens in QAction, but I checked with gdb, the pointers are
> all valid. The slot_foo gets called by a selection in a popup menu. I am
> really at the end of my wits here, since the program really seems to be
> fine. What else could cause this?
I solved my problem partially. It turns out that valgrind lets the program
die when I repeatedly call popup_menu->actions().begin() and .end() in a
for-loop. Seems that in valgrind the iterators might not match or
something. This code however works:
void
Foo::slot_foo(QAction *action)
{
typedef QList<QAction *> Actions;
// Make sure we iterate over one list which is always the same.
Actions actions = popup_menu->actions();
// The following code will segfault in valgrind:
// for (Actions::iterator i = popup_menu->actions().begin();
// popup_menu->actions().end(); ++i) {
for (Actions::iterator i = actions.begin(); i != actions.end(); ++i) {
if (*i != action) {
// un-check all entries
(*i)->setChecked(false);
} else {
// save action mode
action_mode = action_names[action];
// check selected action
(*i)->setChecked(true);
}
}
}
Is this a problem with Qt or rather with Valgrind? What do you think?
--
[ signature omitted ]
Message 3 in thread
Valgrind is correct. You can not iterate over temporary lists. Iterators are
often implemented as pointers into lists or arrays. And your first version
pretty much do this:
Actions::iterator i;
{
Actions a = popup_menu->actions();
i = a.begin();
} // Delete a
while (true) {
{
Actions anotherList = popup_menu->actions();
if (i == anotherList.end())
break;
}
whatever;
++i;
}
Try thinking pointers here, and you'll that this is bad.
And here's a general hint: Always trust valgrind over gdb :-)
Bo.
Thursday 21 December 2006 12:13 skrev Arne Schmitz:
> Arne Schmitz wrote:
> > My program crashes when run in valgrind, but not otherwise:
> >
> > It seems this happens in QAction, but I checked with gdb, the pointers
> > are all valid. The slot_foo gets called by a selection in a popup menu. I
> > am really at the end of my wits here, since the program really seems to
> > be fine. What else could cause this?
>
> I solved my problem partially. It turns out that valgrind lets the program
> die when I repeatedly call popup_menu->actions().begin() and .end() in a
> for-loop. Seems that in valgrind the iterators might not match or
> something. This code however works:
>
> void
> Foo::slot_foo(QAction *action)
> {
> typedef QList<QAction *> Actions;
>
> // Make sure we iterate over one list which is always the same.
> Actions actions = popup_menu->actions();
>
> // The following code will segfault in valgrind:
> // for (Actions::iterator i = popup_menu->actions().begin();
> // popup_menu->actions().end(); ++i) {
>
> for (Actions::iterator i = actions.begin(); i != actions.end(); ++i) {
>
> if (*i != action) {
> // un-check all entries
> (*i)->setChecked(false);
> } else {
> // save action mode
> action_mode = action_names[action];
> // check selected action
> (*i)->setChecked(true);
> }
> }
> }
>
> Is this a problem with Qt or rather with Valgrind? What do you think?
--
[ signature omitted ]
Message 4 in thread
On Thursday 21 December 2006 12:13, Arne Schmitz wrote:
[...]
>
> I solved my problem partially. It turns out that valgrind lets the program
> die when I repeatedly call popup_menu->actions().begin() and .end() in a
> for-loop. Seems that in valgrind the iterators might not match or
> something. This code however works:
[...]
>
>
> Is this a problem with Qt or rather with Valgrind? What do you think?
As Bo explained, STL-style iterators don't work with temporary values. That's
only one of the reasons why we introduced QListIterator<T> and friends. Those
would work fine. Or you could use "foreach":
void Foo::slot_foo(QAction *action)
{
action_mode = action_names[action];
foreach(QAction *otherAction, popup_menu->actions())
otherAction->setChecked(otherAction != action);
}
More information available on
http://doc.trolltech.com/4.2/containers.html#the-iterator-classes
Matthias
--
[ signature omitted ]
Message 5 in thread
Matthias Ettrich wrote:
> As Bo explained, STL-style iterators don't work with temporary values.
> That's only one of the reasons why we introduced QListIterator<T> and
> friends. Those would work fine. Or you could use "foreach":
>
> void Foo::slot_foo(QAction *action)
> {
> action_mode = action_names[action];
> foreach(QAction *otherAction, popup_menu->actions())
> otherAction->setChecked(otherAction != action);
> }
Yes, I am using that now (except that it must be otherAction == action),
since it is very compact but still readable! However, I also tried using
the iterators:
> More information available on
> http://doc.trolltech.com/4.2/containers.html#the-iterator-classes
But then I am getting an error if I use the actions() list to initialize the
iterator. I guess this is again because it's a temporary object that is
returned. At least the constructor of QMutableListIterator wants a
reference as an argument, which a temporary cannot have.
Arne
--
[ signature omitted ]