SourceForge has been redesigned. Learn more.
Close

#349 Segmentation fault with Perl generated wrappers when using __str__

open
nobody
None
4
2014-08-23
2014-04-30
James Damon
No

Hi

I found a case where the Perl swig generation fails. I originally posted on swig-user group, but since then I have found the exact cause of the error:

If I create an interface from this file:

/--------------------------- DIOBuf.i---------------------/
:::C
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%module Test

%{
#include "DIOBuf.h"
%}

%include "DIOBuf.h"

%newobject NewDIOBuf;
/ %delobject DeleteDIOBuf; /

%extend DIOBuf {

DIOBuf( int size ) {
printf("Creating object\n");
return (DIOBuf *)NewDIOBuf( size );
}

~DIOBuf() {
printf("Deleting object\n");
DeleteDIOBuf( $self );
}

const char str() {
return DIOBufToString( $self );
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/
--------------------------------------------------------*/

It will generate the following code method for destroy:
:::perl
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package Test::DIOBuf;
use overload
'""' => sub { $_[0]->str()},
...

sub DESTROY {
return unless $[0]->isa('HASH');
my $self = tied(%{$
[0]});
return unless defined $self;
delete $ITERATORS{$self};
if (exists $OWNER{$self}) {
Testc::delete_DIOBuf($self);
delete $OWNER{$self};
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The problem is that the to_string ( or "" ) operator is overloaded for the Test::DIOBuf object in question. So, after the first delete call of
Testc::delete_DIOBuf($self), the object is deallocated but the interface still has a blessed reference for $self. Hence the next call to delete $OWNER{$self} will use the str method of $self as a key into the %OWNER hash. This is incorrect.

An improved solution is to first save the string representation of $self first, and then using that saved string copy to delete the key from %OWNER after $self no longer is valid and can't be used to produce a string representation.

Here's a solution that I added directly to the Swig file to get this to work.

%perlcode %{
package Test::DIOBuf;
sub newDESTROY {
return unless $[0]->isa('HASH');
my $self = tied(%{$
[0]});
my $tmp = "" . $self;
return unless defined $self;
delete $ITERATORS{$self};
if (exists $OWNER{$self}) {
Testc::delete_DIOBuf($self);
delete $OWNER{$tmp};
}
}
Test::DIOBuf::DESTROY = Test::DIOBuf::newDESTROY;
%}

As for the Swig developers, I have included a patch file fix_perl.patch as well as a testing environment that reproduces the problem. Run "runme.sh" on a Unix based system and it should build you the Perl module as well as run a test case that fails.

2 Attachments

Discussion


Log in to post a comment.