Bah. When I originally wrote this patch, I used a test program and not
the (much) larger (by at least an order of magnitude) program I'm
normally working on. As such, I didn't discover this bug until I tried
to run my larger program against an SDL_Perl with the patch I provided.
The patch attached to this email supersedes the patch I sent in the
email with message-id <[EMAIL PROTECTED]>.
The only change between the previous patch I sent and this one is that
the FreeSurface function won't try to operate on NULL pointers. I
didn't know perl is in the habit of passing NULLs to this function for
some odd reason and both perl's Safefree (which I finally tracked down
to being really Perl_mfree) and SDL_FreeSurface are no-ops if NULL
pointers are passed.
There is still a possible bug if SDL_FreeSurface detects that the
refcount for the surface is greater than one (and then doesn't actually
free the surface) and the surface was created with pre-allocated pixel
memory, which the FreeSurface function will then free. After this,
hijinks will ensue if the surface is then used again. But a cursory
examination of the libSDL source to determine where the refcount of a
surface in could be greater than one was fruitless, so I'm forgetting
about this as a possible problem. It would be cool, had one really felt
the need to fix this, if SDL_FreeSurface returned something other than
void so you could determine if it actually did some free'ing or not
(rather than having to peek at the refcount field in the SDL_Surface
structure), but I digress.
diff -Naur SDL_Perl-2.1.0/src/SDL.xs SDL_Perl-2.1.0-memleak/src/SDL.xs
--- SDL_Perl-2.1.0/src/SDL.xs 2004-03-25 01:41:23.000000000 -0600
+++ SDL_Perl-2.1.0-memleak/src/SDL.xs 2004-07-05 03:06:45.856441242 -0500
@@ -745,7 +745,11 @@
Uint32 Bmask
Uint32 Amask
CODE:
- RETVAL = SDL_CreateRGBSurfaceFrom ( pixels, width, height,
+ Uint8* newpixels;
+ Uint32 size = pitch * height;
+ New(0, newpixels, size, Uint8);
+ Copy(pixels, newpixels, size, Uint8);
+ RETVAL = SDL_CreateRGBSurfaceFrom ( newpixels, width, height,
depth, pitch, Rmask, Gmask, Bmask, Amask );
OUTPUT:
RETVAL
@@ -767,10 +771,9 @@
SDL_Surface *surface
CODE:
Uint8* pixels;
- Uint32 size = surface->pitch * surface->format->BytesPerPixel*
- surface->h;
- pixels = (Uint8*)safemalloc(size);
- memcpy(pixels,surface->pixels,size);
+ Uint32 size = surface->pitch * surface->h;
+ New(0, pixels, size, Uint8);
+ Copy(surface->pixels, pixels, size, Uint8);
RETVAL = SDL_CreateRGBSurfaceFrom(pixels,surface->w,surface->h,
surface->format->BitsPerPixel, surface->pitch,
surface->format->Rmask, surface->format->Gmask,
@@ -782,7 +785,13 @@
FreeSurface ( surface )
SDL_Surface *surface
CODE:
- SDL_FreeSurface(surface);
+ if (surface) {
+ Uint8* pixels = surface->pixels;
+ Uint32 flags = surface->flags;
+ SDL_FreeSurface(surface);
+ if (flags & SDL_PREALLOC)
+ Safefree(pixels);
+ }
Uint32
SurfaceFlags ( surface )