David Christopher Asher wrote:
This works for dynamically allocating memory (an array of char):

SV * create_image(int size) {
    char * image;
    New(0,image,size,char);
    memset(image,CLEAR,size);
    return sv_setref_pv(newSViv(0),"image", (void *)image);
 }

void destroy_image(SV * p) {
    char * image = (char *) SvIV(SvRV(p));
    Safefree(image);
 }


Since you have blessed the reference into package 'image', wouldn't that mean that you would never explicitly call 'destroy_image()' ?
Rather, if I'm not mistaken, you would simply rename 'destroy_image()' to 'DESTROY()' and it would be called automatically for you whenever the reference went out of scope.


I've just been playing around with this aspect - and it seems to work that way.

One thing that puzzles me is that if I explicitly call a destroy() function on a blessed reference, then DESTROY() still gets automatically called - ie the reference apparently gets Safefreed twice. I would expect that such an occurrence should produce an error, but I find that it doesn't.

I also expected that if the reference has been blessed into a package, but there was no 'DESTROY()' function to be found, then perl would complain about that. But that's not the case either :-)

Below is a simple (though not-so-small) demo script of what I'm talking about if anyone is interested .... or even if they're not :-)

Cheers,
Rob

use warnings;

########################################

# Example 1: Unblessed
# Free the memory at each iteration - which I presume is the
# correct thing to do.

for(1..10) {
    $x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
    $y = int(rand(13)) + 1;
    $z = Hmmmm::create_struct($x, $y);
    Hmmmm::clear_mem($z);
    }

print "\n1111\n\n";

########################################

# Example 2: Unblessed
# Same as example 1, but memory is *not* freed at each
# iteration which, I presume, could lead to memory leaks.

for(1..10) {
    $x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
    $y = int(rand(13)) + 1;
    $zz = Hmmmm::create_struct($x, $y);
    }

Hmmmm::clear_mem($zz);

print "\n2222\n\n";

########################################

# Example 3: Blessed
# No need to free the memory as Hmmmm::DESTROY() is called
# automatically when needed. This loop prints out "DESTROY() has
# been called" 9 times, as is to be expected.

for(1..10) {
    $x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
    $y = int(rand(13)) + 1;
    $zzz = Hmmmm::create_struct_blessed($x, $y);
    }

print "\n3333\n\n";

########################################

# Example 4: Blessed
# Exactly the same as Example 3 - only this time we see "DESTROY()
# has been called" 10 times, as is to be expected

for(1..10) {
    $x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
    $y = int(rand(13)) + 1;
    $zzz = Hmmmm::create_struct_blessed($x, $y);
    }

print "\n4444\n\n";

########################################

# Example 5: Blessed
# The same as Examples 3 & 4 - only this time we explicitly call
#'Hmmmm::clear_mem()' && # DESTROY() also gets automatically called.
# Surprisingly (to me) this does not produce any errors

for(1..10) {
    $x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
    $y = int(rand(13)) + 1;
    $zzzz = Hmmmm::create_struct_blessed($x, $y);
    Hmmmm::clear_mem($zzzz);
#    @h = Hmmmm::deref_ref($zzzz);
#    print "@h\n";
    }

print "\n5555\n\n";

########################################

# Now, just prior to exit, $zzz and $zzzz are DESTROY()ed.

package Hmmmm;

use Inline (C => Config =>
            BUILD_NOISY => 1,
            );

use Inline C => <<'EOC';

     typedef struct {
       SV * suit;
       int value;
       } Card;


SV * create_struct(SV * s, int v) { Card * cptr;

New(123, cptr, sizeof(Card), Card);
if(cptr == NULL) croak("Failed to allocate memory in create_struct function");


     cptr->suit = s;
     cptr->value = v;
     return sv_setref_pv(newSViv(0), Nullch, cptr);

}

SV * create_struct_blessed(SV * s, int v) {
     Card * cptr;

New(123, cptr, sizeof(Card), Card);
if(cptr == NULL) croak("Failed to allocate memory in create_struct function");


     cptr->suit = s;
     cptr->value = v;
     return sv_setref_pv(newSViv(0), "Hmmmm", cptr);

}

void deref_ref(SV * p) {
     Inline_Stack_Vars;

     Inline_Stack_Reset;
     Inline_Stack_Push( ((Card *)SvIV(SvRV(p)))->suit );
     Inline_Stack_Push(newSViv(((Card *)SvIV(SvRV(p)))->value));
     Inline_Stack_Done;
     Inline_Stack_Return(2);

}

void clear_mem(SV * p) {
      Card* c = (Card *)SvIV(SvRV(p));
      printf("Clear_mem called\n");
      Safefree(c->suit);
/* c->value is an int, and not to be Safefreed */
      Safefree(c);
}

void DESTROY(SV * p) {
      Card* c = (Card *)SvIV(SvRV(p));
      printf("DESTROY() has been called\n");
      Safefree(c->suit);
/* c->value is an int, and not to be Safefreed */
      Safefree(c);
}



EOC



Reply via email to