fix possible memleak
litter the code with checkpoints to try to track down osx crash
This commit is contained in:
@@ -39,11 +39,20 @@ namespace
|
||||
{
|
||||
void RageFile_png_read( png_struct *png, png_byte *p, png_size_t size )
|
||||
{
|
||||
CHECKPOINT;
|
||||
RageFile *f = (RageFile *) png->io_ptr;
|
||||
|
||||
int got = f->Read( p, size );
|
||||
if( got == -1 )
|
||||
png_error( png, f->GetError() );
|
||||
{
|
||||
/* png_error will call PNG_Error, which will longjmp. If we just pass
|
||||
* GetError().c_str() to it, a temporary may be created; since control
|
||||
* never returns here, it may never be destructed and we could leak. */
|
||||
static char error[256];
|
||||
strncpy( error, f->GetError(), sizeof(error) );
|
||||
error[sizeof(error)-1] = 0;
|
||||
png_error( png, error );
|
||||
}
|
||||
else if( got != (int) size )
|
||||
png_error( png, "Unexpected EOF" );
|
||||
}
|
||||
@@ -56,6 +65,7 @@ struct error_info
|
||||
|
||||
void PNG_Error( png_struct *png, const char *error )
|
||||
{
|
||||
CHECKPOINT;
|
||||
error_info *info = (error_info *) png->error_ptr;
|
||||
strncpy( info->err, error, 1024 );
|
||||
info->err[1023] = 0;
|
||||
@@ -65,6 +75,7 @@ void PNG_Error( png_struct *png, const char *error )
|
||||
|
||||
void PNG_Warning( png_struct *png, const char *warning )
|
||||
{
|
||||
CHECKPOINT;
|
||||
error_info *info = (error_info *) png->error_ptr;
|
||||
LOG->Trace( "loading \"%s\": warning: %s", info->fn, warning );
|
||||
}
|
||||
@@ -93,12 +104,14 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
}
|
||||
|
||||
RageSurface *volatile img = NULL;
|
||||
CHECKPOINT;
|
||||
if( setjmp(png_jmpbuf(png)) )
|
||||
{
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
delete img;
|
||||
return NULL;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
png_set_read_fn( png, f, RageFile_png_read );
|
||||
|
||||
@@ -112,6 +125,7 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
* the image. Just return an empty surface with only the width and height set. */
|
||||
if( bHeaderOnly )
|
||||
{
|
||||
CHECKPOINT;
|
||||
img = CreateSurfaceFrom( width, height, 32, 0, 0, 0, 0, NULL, width*4 );
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
|
||||
@@ -119,6 +133,7 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
}
|
||||
|
||||
|
||||
CHECKPOINT;
|
||||
png_set_strip_16(png); /* 16bit->8bit */
|
||||
png_set_packing( png ); /* 1,2,4 bit->8 bit */
|
||||
|
||||
@@ -168,6 +183,7 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
FAIL_M(ssprintf( "%i", color_type) );
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
if( color_type == PNG_COLOR_TYPE_GRAY )
|
||||
{
|
||||
png_color_16 *trans;
|
||||
@@ -211,6 +227,7 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
|
||||
png_set_interlace_handling( png );
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_update_info( png, info_ptr );
|
||||
|
||||
switch( type )
|
||||
@@ -238,6 +255,7 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
|
||||
/* alloca to prevent memleaks if libpng longjmps us */
|
||||
png_byte **row_pointers = (png_byte **) alloca( sizeof(png_byte*) * height );
|
||||
CHECKPOINT_M( ssprintf("%p",row_pointers) );
|
||||
|
||||
for( unsigned y = 0; y < height; ++y )
|
||||
{
|
||||
@@ -245,8 +263,10 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
row_pointers[y] = p + img->pitch*y;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_image( png, row_pointers );
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_end( png, info_ptr );
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user