[Kde-bindings] QtRuby memleak continued

Richard Dale rdale at foton.es
Fri Sep 1 13:24:15 UTC 2006


On Friday 01 September 2006 13:11, Caleb Tennis wrote:
> > I think the QtRuby code for QStrings is probably wrong, but for 'char *'s
> > I'm
> > not sure as there are no rules for who 'owns' the string after the call
> > has
> > completed. Perhaps we can usually assume QtRuby should delete the 'char
> > *',
> > but special case when it shouldn't - tricky..
>
> I've been pondering this for the past 15 minutes or so now, and I haven't
> thought of any *good* solutions.  I'm curious what PerlQt does to handle
> this, if anything.
Here the code from PerlQt 3.008 for 'char *' marshalling:

static void marshall_charP(Marshall *m) {
    switch(m->action()) {
      case Marshall::FromSV:
	{
	    SV *sv = m->var();
	    if(!SvOK(sv)) {
		m->item().s_voidp = 0;
		break;
	    }
	    if(m->cleanup())
		m->item().s_voidp = SvPV_nolen(sv);
	    else {
		STRLEN len;
		char *svstr = SvPV(sv, len);
		char *str = new char [len + 1];
		strncpy(str, svstr, len);
		str[len] = 0;
		m->item().s_voidp = str;
	    }
	}
	break;
      case Marshall::ToSV:
	{
	    char *p = (char*)m->item().s_voidp;
	    if(p)
		sv_setpv_mg(m->var(), p);
	    else
		sv_setsv_mg(m->var(), &PL_sv_undef);
	    if(m->cleanup())
		delete[] p;
	}
	break;
      default:
	m->unsupported();
	break;
    }
}

And here's the QString marshaller:

static void marshall_QString(Marshall *m) {
    switch(m->action()) {
      case Marshall::FromSV:
	{
	    SV* sv = m->var();
	    QString *s = 0;
	    MAGIC* mg = 0;
	    bool hasMagic = false;
	    if(SvOK(sv) || m->type().isStack()) {
	        if( SvTYPE(sv) == SVt_PVMG  && (mg = mg_find(sv, 
PERL_MAGIC_tiedscalar))
                             && 
sv_derived_from(mg->mg_obj, "Qt::_internal::QString") ) {
                     s = (QString*)SvIV((SV*)SvRV(mg->mg_obj));
                     hasMagic = true;
                } else {
                    COP *cop = cxstack[cxstack_ix].blk_oldcop;
                    if(SvUTF8(sv))
                        s = new QString(QString::fromUtf8(SvPV_nolen(sv)));
                    else if(cop->op_private & HINT_LOCALE)
                        s = new 
QString(QString::fromLocal8Bit(SvPV_nolen(sv)));
                    else
                        s = new QString(QString::fromLatin1(SvPV_nolen(sv)));
		    if( !m->type().isConst() && !m->type().isStack() && !SvREADONLY(sv)) {
                        SV* rv = newSV(0);
                        sv_setref_pv(rv, "Qt::_internal::QString", (void*)s);
                        sv_magic(sv, rv, PERL_MAGIC_tiedscalar, Nullch, 0);
                        hasMagic = true;
		    }
		}
            } else {
		if(!m->type().isConst()) {
		    if(SvREADONLY(sv) && m->type().isPtr()) {
		        m->item().s_voidp = 0;
		        break;    
		    }
		    s = new QString;
		    if( !SvREADONLY(sv) ) {
			SV* rv = newSV(0);
			sv_setpv_mg(sv, "");
                        sv_setref_pv(rv, "Qt::_internal::QString", s);
                        sv_magic(sv, rv, PERL_MAGIC_tiedscalar, Nullch, 0);
		        hasMagic = true;
		    }
		} else
		    s = new QString;
	    }
	    m->item().s_voidp = s;
	    m->next();
	    if(s && !hasMagic && m->cleanup())
		delete s;
	}
	break;
      case Marshall::ToSV:
	{
	    QString *s = (QString*)m->item().s_voidp;
	    if(s) {
		COP *cop = cxstack[cxstack_ix].blk_oldcop;
                if(!(cop->op_private & HINT_BYTES))
                {
		    sv_setpv_mg(m->var(), (const char *)s->utf8());
                    SvUTF8_on(m->var());
                }
                else if(cop->op_private & HINT_LOCALE)
                    sv_setpv_mg(m->var(), (const char *)s->local8Bit());
                else
                    sv_setpv_mg(m->var(), (const char *)s->latin1());
            }
	    else
		sv_setsv_mg(m->var(), &PL_sv_undef);
	    if(m->cleanup())
		delete s;
	}
	break;
      default:
	m->unsupported();
	break;
    }
}

Hmm, it looks like it has a bit more code - I wonder if I've missed some 
functionality converting to Ruby. It does use an isConst() check along with  
if( !SvREADONLY(sv) ) which doesn't have an equivalent in Ruby to set a 
boolean called 'hasMagic'. Then it only deletes the QString if hasMagic is 
false.

-- Richard



More information about the Kde-bindings mailing list