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

Can anyone explain what the macro MEM_WRAP_CHECK_1 is checking for?

And how calling the callback() sub below, with the commented out line enabled, would cause that macro to be invoked, and fail, producing the message "panic: memory wrap at...", but not when the line is disabled?

SV *g_rec = 0; int setCallback( SV* rec ) { g_rec = rec; SvREFCNT_inc( g_rec ); return 0; } void callback() { // call_sv( g_rec, 0); }

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re: panic: memory wrap
by dave_the_m (Monsignor) on Nov 14, 2005 at 01:59 UTC
    Can anyone explain what the macro MEM_WRAP_CHECK_1 is checking for?
    Consider if your code does New(p, 0x40000000, int). Perl will try to do malloc(0x40000000 x sizeof(int)), but on a 32-bit system that would wrap round to malloc(0). The macro's there to check for it.
    And how calling the callback() sub below, with the commented out line enabled, would cause that macro to be invoked, and fail, producing the message "panic: memory wrap at...", but not when the line is disabled?
    Something called by the call_sv() is trying to allocate a very large structure. We can't tell what from the information supplied.

    Dave.

      I managed to reproduce the problem in a standalone testcase.

      It seems that the different coderef values from Perl and XS are a red herring. I guess dereferencing a coderef in Perl has some indirection magic that I don't understand, because I get different values in the following test script, but that doesn't stop it from working?

      #! perl -slw use strict; use Inline 'NoClean', 'FORCE', 'INFO' ; use Inline Config => WARNINGS => 4; use Inline 'C' => 'DATA', NAME =>'test'; sub recorder{ print "record: @_"; } sub player{ print "player: @_"; } printf "r:%x p:%x\n", \&recorder, \&player; setCallbacks( \&recorder, \&player ); record( 'test' ); #record( 'test' ); #play( 'test' ); __DATA__ __C__ SV *g_rec = 0, *g_play = 0; int setCallbacks( SV *rec, SV *play ) { printf( "r:%x p:%x\n", rec, play ); g_rec = rec; SvREFCNT_inc( g_rec ); g_play = play; SvREFCNT_inc( g_play ); return 0; } int record( SV *m ) { call_sv( g_rec, G_VOID ); return 0; } int play( SV *m ) { call_sv( g_play, G_VOID ); return 0; }

      As is, with the second call to record() and that to play() commented out, the program runs fine

      P:\test>test r:226004 p:2260b8 r:19499e4 p:2252a8 record: test

      Different addresses(?), but it works. Remove either comment and it panics.

      P:\test>test r:226004 p:2260b8 r:19499e4 p:2252a8 record: test panic: memory wrap at P:\test\test.pl line 16.

      I assume that it is something to do with my (lack of) handling of the stack(?), but I've tried various combinations of the Inline_* macros without success.

      Cluebats gratefully receieved.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        The \ operator creates a temporary reference, which is usually freed at the end of the current statement. You're saving that tmp ref. Instead, just store the the thing pointed by the ref, ie the CV.

        Dave.

      The code I am trying to call back is currently just

      sub recorder { print "@_"; }

      However, I just checked the address I am passing in from Perl, and the address the SetCallback code receives, and they are different? Which explains why it doesn't work, and probably the error message, but not why/how/where the address is being changed. The calling code looks like this:

      printf "Address passed from Perl to C: %x\n", \&recorder; setHooks( \&recorder, \&player ) and die "$^E";

      and setHooks() like this

      SV *g_rec = 0, *g_play = 0; int setHooks( SV* rec, SV* play ) { HANDLE hHook = GetModuleHandle( "hook" ); printf( "SH rec:%x\n", rec ); g_rec = rec; SvREFCNT_inc( g_rec ); printf( "SH g_rec:%x\n", g_rec ); // SvREFCNT_inc( g_play = play ); ... }

      And the output from those print and printf statements on either side of the call is:

      Address passed from Perl to C: 1950428 SH rec:1d2ef20 SH g_rec:1d2ef20

      So, at least I now know where it's going wrong, if not why. Thanks for your help.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re: panic: memory wrap
by Will_the_Chill (Pilgrim) on Dec 23, 2013 at 12:15 UTC
    BrowserUk,

    I totally needed the answer to this question for RPerl. Thank goodness for you and Dave, and thank goodness for Perl Monks!

    Perling,
    ~ Will the Chill