On May 18, 2007, at 2:58 AM, Xavier Noria wrote:

OK, I've got something. Very misterious!!!

Fortunately the segmentation fault happens in the first call to the function and some printfs where enough to arrive to what seems the key.

The C subroutine receives an array in its second argument:

  int __next_partition_of_size_p(SV* k_avptr, SV* M_avptr, int p) {
      AV* k = GETAV(k_avptr);
      AV* M = GETAV(M_avptr);
      ...
  }

that is initialized in the Perl side:

  my @M = (0) x $q;
  push @M, $_ - $q + 1 for $q..(@$data-1);
  ...
  __next_partition_of_size_p([EMAIL PROTECTED], [EMAIL PROTECTED], $p)

The values of $q and @$data do not matter, they are correct. OK, [EMAIL PROTECTED] is passed to the function as the second argument, and if I print its contents in XS I get garbage from some index on. Just in case, that call lives in a closure:

  my $iter = Algorithm::Combinatorics::Iterator->new(sub {
      __next_partition_of_size_p([EMAIL PROTECTED], [EMAIL PROTECTED], $p) == 
-1 ? ...;
  }, __slice_partition_of_size_p([EMAIL PROTECTED], $p, $data));


NOW THE MISTERY COMES, If I just print @M in Perl before that line, the values in XS are right and execution completes without errors. I mean, I just really added

  print join(", ", @M), "\n";

before the call and all of a sudden the values of M in the XS side are fine and thus the code completes OK.

I am puzzled here! Any ideas?

That was the key in fact.

Problem was in 5.6.x there's no guarantee simple arithmetic with integers gives an SV with a IV slot:

$ ~/local/perl-5.6.2/bin/perl -MDevel::Peek -e '$a = 1; $b = $a + 1; Dump $b'
  SV = NV(0x180a810) at 0x1807730
    REFCNT = 1
    FLAGS = (NOK,pNOK)
    NV = 2

Since the macro I used to pick integers was SvIVX my code was broken in that version. Switching to SvIV is all I need to fix the module for 5.6.x.

This changed in 5.8:

Perl now tries internally to use integer values in numeric conversions
  and basic arithmetics (+ − * /) if the arguments are integers, and
  tries also to keep the results stored internally as integers.  This
  change leads to often slightly faster and always less lossy arith‐
metics. (Previously Perl always preferred floating point numbers in its
  math.)

But now that I reread that delta I see it just says "tries", so from a formal point of view my use of SvIVX was incorrect even in 5.8.x, albeit it worked in practice.

Marvin, thank you very much for your help.

-- fxn


Reply via email to