Tels <[EMAIL PROTECTED]> writes:
>-----BEGIN PGP SIGNED MESSAGE-----
>
>Moin,
>
>I have written a (simple?) routine in XS that uses the GMP library to 
>calculate the modular inverse. When running a small test file, it segfaults 
>at the end of the testfile like this:
>
>       ...
>       ok 253
>       ok 254
>       ok 255
>       Segmentation fault
>
>Running it under valgrind gives the text below.
>
>Here is the XS code. I have tried several variations, but to no avail (I 
>really don't know what I do, maybe I should first read the Perl Embedding 
>book fully :) Does somebody spot something wrong or something I could do 
>better?

valgrid is complaining about XS_Math__BigInt__GMP_DESTROY
can we see that please?

>
>The routine basically only returns (undef,undef) (but not in my testcase!) or 
>(4404, '+'). The case of ($somenumber, '-') shouldn't happen (and does not in 
>my testcase, anyway).
>
>void
>_modinv(class,x,y)
>        SV*     class
>        mpz_t*  x
>        mpz_t*  y
>
>  PREINIT:
>    int rc, sign;
>    SV* s;
>  PPCODE:
>    rc = mpz_invert(*x, *x, *y);
>    EXTEND(SP, 2);      /* we return two values */
>    if (rc == 0)
>      {
>      /* inverse doesn't exist, return value undefined */
>      PUSHs ( &PL_sv_undef );
>      PUSHs ( &PL_sv_undef );
>      }
>    else
>      {
>      /* inverse exists, get sign */
>      sign = mpz_sgn (*x);
>      /* absolute result */
>      mpz_abs (*x, *x);
>      PUSHs(sv_setref_pv(sv_newmortal(), "Math::BigInt::GMP", (void*)x));

That is probably wrong. A pv is a char * and perl is going to do strlen()
on it and strcpy() it into memory allocated by perl's New().
My guess is x is already malloc()'ed or C++ new'ed by mpz stuff.
In such cases it is usual to use sv_setref_iv(...,PTR2IV(x)),
and then have DESTROY function call the inner library's free() routine.
If *x is a struct then it may also be apprpriate to put the struct
as binary data in a PV - but there isn't a handy create-blessed-ref
function to do that, you need to do it long-hand
something like:

  SV *sv = sv_bless(new_RV(newSVpv(x,sizeof(*x))),gv_stashpv("...", TRUE));

(Trying to do that in one expression may be too rich for some compilers
when all macros are expanded.)

The other issue you _may_ be having is that *x came in from an SV 
(possibly tempoary). Unless *x is refcounted in mpz library you need 
get library to give you a new one to return from the XSUB to another perl
SV, or change perl view of API to mimic the library's modify-in-place
semantics. Otherwise both SVs will call DESTROY and try and free(x).


>      if (sign >= 0)
>        {
>        PUSHs ( &PL_sv_undef ); /* result is ok, keep it */
>        }
>      else
>        {
>        s = sv_newmortal();
>        sv_setpvn (s, "-", 1);
>        PUSHs ( s );            /* result must be negated */
>        }
>      }
>
>I tried to allocate a new GMP object and return a ref to that instead, but 
>this is exactly the same segfault.
>
>Thank you in advance,
>
>Tels
>
>ok 255
>==5047== Invalid read of size 4
>==5047==    at 0x41F090A5: __gmpz_clear (in /usr/lib/libgmp.so.3.3.2)
>==5047==    by 0x41ED12A1: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==    by 0x80C2786: Perl_pp_entersub (in /usr/bin/perl)
>==5047==    by 0x8060DCE: Perl_call_sv (in /usr/bin/perl)
>==5047==    Address 0x41D18D4C is 0 bytes inside a block of size 12 free'd
>==5047==    at 0x40028E01: free (in /usr/lib/valgrind/vgskin_memcheck.so)
>==5047==    by 0x41ED12A9: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==    by 0x80C2786: Perl_pp_entersub (in /usr/bin/perl)
>==5047==    by 0x8060DCE: Perl_call_sv (in /usr/bin/perl)
>==5047==
>==5047== Invalid read of size 4
>==5047==    at 0x41F090AE: __gmpz_clear (in /usr/lib/libgmp.so.3.3.2)
>==5047==    by 0x41ED12A1: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==    by 0x80C2786: Perl_pp_entersub (in /usr/bin/perl)
>==5047==    by 0x8060DCE: Perl_call_sv (in /usr/bin/perl)
>==5047==    Address 0x41D18D54 is 8 bytes inside a block of size 12 free'd
>==5047==    at 0x40028E01: free (in /usr/lib/valgrind/vgskin_memcheck.so)
>==5047==    by 0x41ED12A9: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==    by 0x80C2786: Perl_pp_entersub (in /usr/bin/perl)
>==5047==    by 0x8060DCE: Perl_call_sv (in /usr/bin/perl)
>==5047==
>==5047== Invalid free() / delete / delete[]
>==5047==    at 0x40028E01: free (in /usr/lib/valgrind/vgskin_memcheck.so)
>==5047==    by 0x41F010BC: __gmp_default_free (in /usr/lib/libgmp.so.3.3.2)
>==5047==    by 0x41F090BB: __gmpz_clear (in /usr/lib/libgmp.so.3.3.2)
>==5047==    by 0x41ED12A1: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==    Address 0x41D18D88 is 0 bytes inside a block of size 8 free'd
>==5047==    at 0x40028E01: free (in /usr/lib/valgrind/vgskin_memcheck.so)
>==5047==    by 0x41F010BC: __gmp_default_free (in /usr/lib/libgmp.so.3.3.2)
>==5047==    by 0x41F090BB: __gmpz_clear (in /usr/lib/libgmp.so.3.3.2)
>==5047==    by 0x41ED12A1: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==
>==5047== Invalid free() / delete / delete[]
>==5047==    at 0x40028E01: free (in /usr/lib/valgrind/vgskin_memcheck.so)
>==5047==    by 0x41ED12A9: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==    by 0x80C2786: Perl_pp_entersub (in /usr/bin/perl)
>==5047==    by 0x8060DCE: Perl_call_sv (in /usr/bin/perl)
>==5047==    Address 0x41D18D4C is 0 bytes inside a block of size 12 free'd
>==5047==    at 0x40028E01: free (in /usr/lib/valgrind/vgskin_memcheck.so)
>==5047==    by 0x41ED12A9: XS_Math__BigInt__GMP_DESTROY (in /home/te/perl/
>math/Math-BigInt-GMP-1.13/blib/arch/auto/Math/BigInt/GMP/GMP.so)
>==5047==    by 0x80C2786: Perl_pp_entersub (in /usr/bin/perl)
>==5047==    by 0x8060DCE: Perl_call_sv (in /usr/bin/perl)
>==5047==
>==5047== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 4 from 1)
>==5047== malloc/free: in use at exit: 613982 bytes in 12112 blocks.
>==5047== malloc/free: 32648 allocs, 20538 frees, 12875889 bytes allocated.
>==5047== For a detailed leak analysis,  rerun with: --leak-check=yes
>==5047== For counts of detected errors, rerun with: -v
>
>
>- -- 
> Signed on Sat Jan 10 16:03:05 2004 with key 0x93B84C15.
> Visit my photo gallery at http://bloodgate.com/photos/
> PGP key on http://bloodgate.com/tels.asc or per email.
>
> "Yeah. Whatever."
>
>-----BEGIN PGP SIGNATURE-----
>Version: GnuPG v1.2.2-rc1-SuSE (GNU/Linux)
>Comment: When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl.
>
>iQEVAwUBQAAV0HcLPEOTuEwVAQEy2gf/UtDtuHq6Xy2qpsr6kqanvcVZcc4mKBDq
>RAvqnuE/1izRCN9VyLS18f4CR6nzJ3mS05lhZl9EfJWf1zrcls4UlvRCerdCq533
>aK81kEqfBA8De8++pEESs5sS3XSKz+jaM5mh0Drem4SeArulY2+a+WlFRc3VcLi5
>Zj+SU9brxlWV/rcM4LYJxZB10unusaDtTFI3VUJROPIb8DSAa7NT11GPgt9czVtx
>vsUUPDJYQFep7xEmXy8oKWN5cOjFlRfHLUSlziezWuQZ5Bf3o26vPY9uVzGNJ/Iu
>SAZ8XhiS24XBRKR98y5EWy3mBOs+kCjr5cdy3yG1c0hP1lwDMlx5Yw==
>=5EeZ
>-----END PGP SIGNATURE-----

Reply via email to