[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