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-----