syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

For quite a few years I have been building various (and numerous) perl extensions on MinGW-built perl, and then installing those builds on ActivePerl. This has always worked fine - and I can't think of any reason that it shouldn't work fine.

Disturbingly, however, I've now come across a situation where a MinGW-built extension exhibits different behaviour when run on ActivePerl. This applies only to perls 5.10.0 and 5.10.1. Afaict, earlier perls are fine.
Here's the Inline::C demo:
use warnings; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; void foo() { printf("%d\n", GIMME_V == G_ARRAY); } EOC my $x = [foo()];
To see what I'm getting, you'll need ActivePerl 5.10.x (set up to use the MinGW compiler), MinGW-built perl 5.10.x (Strawberry Perl 5.10.x will do), along with Inline-0.45 installed on both of those perls.

Then you'll find that if you run that script using the MinGW-built perl 5.10.x, it will compile and output 1. If you then run the very same script (in the very same location) on ActivePerl 5.10.x, then the script does not get re-compiled (nor should it), and the output is 0. ("x" can be either 0 or 1, but it's important that "x" has the same value for both perls - otherwise you'll get separate compilations, in which case the output will always be 1.)

Alternatively, you can first run (and compile) the script with ActivePerl, and then re-run the script on MinGW-built perl. If you do that, the outputs are reversed - ActivePerl now outputs 1, and MinGW-built perl outputs 0. That is, the output toggles, depending upon which perl actually compiles the script.

This completely baffles me - it is the only instance I have ever come across where the behaviour changes from one platform to the other. Does anyone have any insight into why this happens ?

I came across this while building Net::SSH2. That is, I built Net-SSH2-0.28 on MinGW-built 5.10.0 where it built and passed its test suite, and then installed that build onto ActivePerl 5.10.0 where it failed some of the tests in the test suite (because GIMME_V == G_ARRAY in an XSub was being evaluated differently from one perl to the other). This strikes me as very peculiar - identical site/lib/Net/SSH2.pm and site/lib/auto/Net/SSH2/SSH2.dll files behaving differently. How can this be ? Why does it happen only with 5.10 ? Why haven't I been bitten by this type of thing before ?

Cheers,
Rob

Replies are listed 'Best First'.
Re: GIMME_V==G_ARRAY anomaly on win32 (5.10 only)
by BrowserUk (Patriarch) on Dec 18, 2009 at 15:33 UTC

    I'm not in a position to test my speculation, but the only possibility that crosses my mind is that the internal representation of boolean true/false varies between the two compilers somehow.

    And that when you supply that value and ask printf to interpret it as a signed integer (%d), the internal representation generated by one compiler is misinterpreted by the CRT of the other.

    Possible ways to confirm this might include:

    printf("%d\n", (int)GIMME_V == G_ARRAY); printf("%d\n", GIMME_V == G_ARRAY ? 1 : 0 );

    Just a thought.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      the only possibility that crosses my mind is that the internal representation of boolean true/false varies between the two compilers somehow

      The thing is that there's only *one* compiler. Irrespective of whether I compile the script with ActivePerl or MinGW-built perl, it's the one and same (gcc-3.4.5) compiler that's doing the compilation.
      Admittedly that's not the compiler that actually *built* ActivePerl, but it does use the same CRT as the compiler that built ActivePerl - which is one reason that I expect to *not* be confronted with this sort of problem :-)

      The more I think about it, the weirder it seems. I'll play around with it myself a little more today, and then maybe post to p5p as ikegami suggests. I'm a little hesitant to post there as the description of what I'm doing and how to run the demo is somewhat messy - even though what I'm doing is really quite straight forward.
      Maybe I can clean the description up a little.

      Thanks for the thoughts - and please don't hesitate to present any others you may have. I've added your 2 printf() calls to the script in case they provide some help somewhere down the track.

      Cheers,
      Rob
        Admittedly that's not the compiler that actually *built* ActivePerl, ...

        My speculation would be that this is the problem (but I don't have the prerequisites here to try).  GIMME_V is a rather complex macro which accesses code in the perl binary (without using the CRT, so it's irrelevant that the CRT is the same). G_ARRAY, OTOH, is a simple constant that gets compiled directly into the extension DLL. In other words, you are mixing code compiled with different compilers, but if you recompile, the macro presumably is being expanded appropriately...

        but it does use the same CRT as the compiler that built ActivePerl

        My final speculation. Does this change anything?

        use warnings; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; int junk( int val ) { return printf( "%d\n", val ); } void foo() { junk( GIMME_V == G_ARRAY ); } EOC my $x = [foo()];

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        What's the result matrix for
        void foo() { printf("%x\n", GIMME_V); printf("%x\n", G_ARRAY); printf("%d\n", GIMME_V == G_ARRAY); }

        Maybe it would help if you posted the generated C and XS files for each Perl. They normally get deleted, but you can avoid that with

        perl -MInline=NOCLEAN,force script.pl

        ( "force" forces a rebuild )

Re: GIMME_V==G_ARRAY anomaly on win32 (5.10 only)
by ikegami (Patriarch) on Dec 18, 2009 at 15:53 UTC
    Played around a bit and no idea. Maybe ask on p5p? ( bah, should have checked for other responses first )
Re: GIMME_V==G_ARRAY anomaly on win32 (5.10 only) - SOLVED
by syphilis (Archbishop) on Dec 19, 2009 at 23:35 UTC
    Turns out almut was right (surprise, surprise).

    Thinking about the points that she had been pushing, I finally remembered the CCFLAGS option "-mms-bitfields" which ActivePerl use, but my MinGW-built perl (and also my Strawberry Perl) do not.
    I'm not exactly clear on the details of what this flag does, but from the brief reading I did (and just from its name), it seemed like it might be capable of producing the behaviour I was seeing.

    Sure enough, when I build perl 5.10 using MinGW *with* -mms-bitfields, the problem goes away.
    This also validates ikegami's suggestion of posting to p5p - as I'm sure someone there would have tweaked to what was happening straight away.

    I can now understand the problem (to a level that I find satisfactory) - which is quite a relief.

    Thanks again, almut.

    Cheers,
    Rob

    UPDATE: Although I got the remedy right, I still didn't get the diagnosis *quite* right. (In fact, I was a long way off.) Having sought some thoughts from p5p, Jan Dubois replied and cleared up my mis-conceptions. He also asked that I update this thread with the corrections - so, to do that, I'll just reproduce his reply (which was also sent to p5p and is thus already in the public domain) to my original email: