Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 4

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 ]