[Kde-bindings] new QApplication and MethodCall cleanup

Richard Dale rdale at foton.es
Tue Aug 5 09:57:49 UTC 2008


On Tuesday 05 August 2008 10:48:27 Phil Thompson wrote:
> On Tue, 5 Aug 2008 02:17:44 -0700, "Chris Burel" <chrisburel at gmail.com>
>
> wrote:
> > I've been trying to get Hello World! to work in Perl and Qt4 for the past
> > couple weeks, and the problem that I've really been battling is a
>
> segfault
>
> > when I call $label->show().  The backtrace showed it failing in libc's
> > strlen() function.  I eventually traced it down to the fact that since we
> > pass in a char** to the QApplication, when it goes to show the
> > application,
> > it tries to access the data stored by that pointer.  But in the PerlQt3
> > code, and qtruby4, the MethodCall object cleanup() method returns true,
>
> so
>
> > that memory has already been cleared by the marshall_charP_array handler
> > fn
> > ('rb_ary_clear(arglist);' in qtruby and by 'av_clear(arglist);' perlqt3).
> >
> > How is this working?  As soon as I change the MethodCall cleanup() method
> > to
> > return false, the $label->show works fine.  Obviously that's not the real
> > solution, and the other bindings are getting around this somehow.
>
> I'm not sure if it's the same issue, but Qt4's QApplication ctors keep a
> pointer to the argc parameter and dereference it later on. With C++ argc is
> on the stack but that's Ok because that part of the stack will never be
> popped until the application exits. With other languages argc is more
> likely to be on the heap and to be garbage collected too soon.
>
> The PyQt solution is to save argc in a local static int and pass that to
> the QApplication ctors.

This is the code in QtRuby that creates the argc 'char **' array given a Ruby 
Array of strings:

	    char **argv = new char *[RARRAY(arglist)->len + 1];
	    long i;
	    for(i = 0; i < RARRAY(arglist)->len; i++) {
                VALUE item = rb_ary_entry(arglist, i);
                char *s = StringValuePtr(item);
                argv[i] = new char[strlen(s) + 1];
                strcpy(argv[i], s);
	    }

So it mallocs the array of char *s, and then creates a new copy of the Ruby 
StringValuePtr that contains the data in each Ruby String.

It doesn't attempt to delete the 'argv' array after the call. The code after 
cleanup just recreates the Ruby array from whatever was in the argv array 
after the call:

		rb_ary_clear(arglist);
		for(i = 0; argv[i]; i++) {
		    rb_ary_push(arglist, rb_str_new2(argv[i]));
	        }

I think the assumption is that a 'char **' argument type will always expect to 
hang around after the call for the life of the program and that a leak is 
acceptable. I don't think I know of any cases in the Qt or KDE apis where 
they are expected to only be around for the life of the method call. I would 
hope that a QStringList is usually used instead.

-- Richard




More information about the Kde-bindings mailing list