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 )
|
void RageFile_png_read( png_struct *png, png_byte *p, png_size_t size )
|
||||||
{
|
{
|
||||||
|
CHECKPOINT;
|
||||||
RageFile *f = (RageFile *) png->io_ptr;
|
RageFile *f = (RageFile *) png->io_ptr;
|
||||||
|
|
||||||
int got = f->Read( p, size );
|
int got = f->Read( p, size );
|
||||||
if( got == -1 )
|
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 )
|
else if( got != (int) size )
|
||||||
png_error( png, "Unexpected EOF" );
|
png_error( png, "Unexpected EOF" );
|
||||||
}
|
}
|
||||||
@@ -56,6 +65,7 @@ struct error_info
|
|||||||
|
|
||||||
void PNG_Error( png_struct *png, const char *error )
|
void PNG_Error( png_struct *png, const char *error )
|
||||||
{
|
{
|
||||||
|
CHECKPOINT;
|
||||||
error_info *info = (error_info *) png->error_ptr;
|
error_info *info = (error_info *) png->error_ptr;
|
||||||
strncpy( info->err, error, 1024 );
|
strncpy( info->err, error, 1024 );
|
||||||
info->err[1023] = 0;
|
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 )
|
void PNG_Warning( png_struct *png, const char *warning )
|
||||||
{
|
{
|
||||||
|
CHECKPOINT;
|
||||||
error_info *info = (error_info *) png->error_ptr;
|
error_info *info = (error_info *) png->error_ptr;
|
||||||
LOG->Trace( "loading \"%s\": warning: %s", info->fn, warning );
|
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;
|
RageSurface *volatile img = NULL;
|
||||||
|
CHECKPOINT;
|
||||||
if( setjmp(png_jmpbuf(png)) )
|
if( setjmp(png_jmpbuf(png)) )
|
||||||
{
|
{
|
||||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||||
delete img;
|
delete img;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
CHECKPOINT;
|
||||||
|
|
||||||
png_set_read_fn( png, f, RageFile_png_read );
|
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. */
|
* the image. Just return an empty surface with only the width and height set. */
|
||||||
if( bHeaderOnly )
|
if( bHeaderOnly )
|
||||||
{
|
{
|
||||||
|
CHECKPOINT;
|
||||||
img = CreateSurfaceFrom( width, height, 32, 0, 0, 0, 0, NULL, width*4 );
|
img = CreateSurfaceFrom( width, height, 32, 0, 0, 0, 0, NULL, width*4 );
|
||||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
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_strip_16(png); /* 16bit->8bit */
|
||||||
png_set_packing( png ); /* 1,2,4 bit->8 bit */
|
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) );
|
FAIL_M(ssprintf( "%i", color_type) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHECKPOINT;
|
||||||
if( color_type == PNG_COLOR_TYPE_GRAY )
|
if( color_type == PNG_COLOR_TYPE_GRAY )
|
||||||
{
|
{
|
||||||
png_color_16 *trans;
|
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 );
|
png_set_interlace_handling( png );
|
||||||
|
|
||||||
|
CHECKPOINT;
|
||||||
png_read_update_info( png, info_ptr );
|
png_read_update_info( png, info_ptr );
|
||||||
|
|
||||||
switch( type )
|
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 */
|
/* alloca to prevent memleaks if libpng longjmps us */
|
||||||
png_byte **row_pointers = (png_byte **) alloca( sizeof(png_byte*) * height );
|
png_byte **row_pointers = (png_byte **) alloca( sizeof(png_byte*) * height );
|
||||||
|
CHECKPOINT_M( ssprintf("%p",row_pointers) );
|
||||||
|
|
||||||
for( unsigned y = 0; y < height; ++y )
|
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;
|
row_pointers[y] = p + img->pitch*y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHECKPOINT;
|
||||||
png_read_image( png, row_pointers );
|
png_read_image( png, row_pointers );
|
||||||
|
|
||||||
|
CHECKPOINT;
|
||||||
png_read_end( png, info_ptr );
|
png_read_end( png, info_ptr );
|
||||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user