Well ... there may well be something not right with perl - but afaict there is something not right with GD-2.30, either. The following script outputs "11037 11037 ERROR 1", but surely $raw and $raw2 should be equivalent. (Note that I'm looping thru the loop only once .... which means I'm not really looping at all :-)
use strict;
use warnings;
use GD;
for(1 .. 1) {
x(100, 100);
print $_, " ";
}
sub x{
my $im = GD::Image->new( @_);
my $raw = $im->gd;
my $im2 = GD::Image->newFromGdData( $raw ) or die "$!, $^E";
my $raw2 = $im2->gd;
# my $len = length($raw);
if($raw ne $raw2) {print length($raw), " ", length($raw2), " ERROR
+ "}
}
If I then remove the '#' so that the length of $raw is evaluated, the script then outputs "1 " - which is as I would expect.
And when I further change the script so that it loops 10 times, I get the "Free to wrong pool..." error immediately (irrespective of whether the length of $raw is evaluated or not). Contrast that behaviour with the following Inline::C script that does (I believe) precisely the same thing - but manages to interface with the GD library flawlessly. (You'll probably need to amend the 'LIBS' and 'INC' config info.)
use warnings;
package my_gd;
use Inline C => Config =>
BUILD_NOISY => 1,
LIBS => '-LD:/gd/gdwin32 -lbgd',
INC => '-ID:/gd/gdwin32/include';
use Inline C => <<'EOC';
#include <stdio.h>
#include <gd.h>
SV * new(int x, int y) {
gdImagePtr * image;
SV * obj_ref, *obj;
New(1, image, 1, gdImagePtr);
if(image == NULL)croak("Failed to allocate memory in new()");
obj_ref = newSViv(0);
obj = newSVrv(obj_ref, "my_gd");
*image = gdImageCreate(x, y);
sv_setiv(obj, (IV)image);
SvREADONLY_on(obj);
return obj_ref;
}
SV * gdgdImageCreateFromGdPtr(SV * data, int len) {
gdImagePtr * image;
SV * obj_ref, *obj;
New(1, image, 1, gdImagePtr);
if(image == NULL)croak("Failed to allocate memory in gdgdImageCre
+ateFromGdPtr()");
obj_ref = newSViv(0);
obj = newSVrv(obj_ref, "my_gd");
*image = gdImageCreateFromGdPtr(len, SvPV(data, len));
sv_setiv(obj, (IV)image);
SvREADONLY_on(obj);
return obj_ref;
}
SV * gdgd(SV * image) {
void * data;
int size;
SV * t;
data = gdImageGdPtr(*((gdImagePtr *)SvIV(SvRV(image))), &size);
t = newSVpv((char*) data, size);
gdFree(data);
return t;
}
void DESTROY(SV * image) {
printf("Destroying ");
Safefree((gdImagePtr *)SvIV(SvRV(image)));
}
EOC
$| = 1;
for(1 .. 10) {
x(100, 100);
print $_, " ";
}
sub x{
my $im = new(@_);
my $raw = gdgd($im);
my $im2 = gdgdImageCreateFromGdPtr($raw, length($raw));
my $raw2 = gdgd($im2);
# print length($raw), " ";
if($raw ne $raw2) {print "ERROR"}
}
Note that DESTROY() prints "Destroying " - just so you can see that/when it's being called. It's probably less confusing if you comment that out.
I'm going to stop short of saying that there is something wrong with the GD-2.30 source - I'm not all that familiar with either the GD library or the perl module, and I might be doing something (embarrassingly) stupid. But I feel that it's possible to write the perl interface to the GD library in such a way that the errors we're seeing with the GD module do not occur.
Cheers, Rob |