From fc78e9e4c8a35717ebf3e2827b30f13dbfcd3191 Mon Sep 17 00:00:00 2001
From: Phil Rosenberg <p.d.rosenberg@gmail.com>
Date: Tue, 8 Mar 2016 21:03:55 +0000
Subject: [PATCH 1/4] Added functions that will record memory allocations in
 the PLStream

These are the start of a new memory management system that will
hopefully contribute to removal of exit() calls. The new memory
allocation/deallocation finctions plmalloc, plrealloc and plfree work
just like the standard malloc, realloc and free, but all memory
allocations are recorded in the PLStream passed to these functons too.

The list of allocated memory is marked at API entry and therefore on
exit any "forgotten" memory can be freed. Memory allocation is checked
and plexit called if it fails. Although plexit is still called, it
removes the requirement for each call to get memory to check for
success. In the future the plexit call can be replaced with a longjmp
call.
---
 include/plstrm.h |   6 ++
 src/plcore.c     | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+)

diff --git a/include/plstrm.h b/include/plstrm.h
index 797df96..1064c91 100644
--- a/include/plstrm.h
+++ b/include/plstrm.h
@@ -800,6 +800,12 @@ typedef struct
 //
     char *mf_infile;
     char *mf_outfile;
+
+// Memory allocation records, to allow us to free any left over memory
+// before we return from an API call and avoid memory leaks
+    void **memorylist;
+    void **memorylisthead;
+    void **memorylistend;
 } PLStream;
 
 //--------------------------------------------------------------------------
diff --git a/src/plcore.c b/src/plcore.c
index db12184..f65ba8f 100644
--- a/src/plcore.c
+++ b/src/plcore.c
@@ -93,6 +93,131 @@ text2num( PLCHAR_VECTOR text, char end, PLUNICODE *num );
 int
 text2fci( PLCHAR_VECTOR text, unsigned char *hexdigit, unsigned char *hexpower );
 
+//Initialise the list of allocated memory. This should be called in every API
+//entry function. Note also that we can have reentrant behaviour, so this function
+//can be called when we already have a list of memory. Therefore when this function
+//is called we add NULL to the list.
+void
+plinitialisememorylist( PLStream *pls )
+{
+    //create a new memory list if needed
+    if ( !pls->memorylist )
+    {
+        pls->memorylist = malloc( 10 * sizeof ( void* ) );
+        if ( !pls->memorylist )
+            plexit( "Memory allocation failure in plinitialisememorylist." );
+        pls->memorylisthead = pls->memorylist;
+        pls->memorylistend  = pls->memorylist + 10;
+    }
+
+    //expand the memory list if needed so we have space for our NULL entry
+    if ( pls->memorylisthead == pls->memorylistend )
+    {
+        size_t n = ( pls->memorylistend - pls->memorylist ) * 2;
+        realloc( pls->memorylist, n * sizeof ( void* ) );
+        pls->memorylisthead = pls->memorylist + n / 2;
+        pls->memorylistend  = pls->memorylist + n;
+    }
+
+    //add a null pointer to mark the API entry
+    *( pls->memorylisthead ) = NULL;
+    ++pls->memorylisthead;
+}
+
+//Allocate some memory, record it in the PLStream memory list
+//and return the address of the start of the memory
+void *
+plmalloc( PLStream *pls, size_t size )
+{
+    //allocate the new memory and check it
+    void *mem = malloc( size );
+    if ( !mem )
+        plexit( "Memory allocation failure in plmalloc." );
+    //expand the memory list if needed
+    if ( pls->memorylisthead == pls->memorylistend )
+    {
+        size_t n = ( pls->memorylistend - pls->memorylist ) * 2;
+        realloc( pls->memorylist, n * sizeof ( void* ) );
+        pls->memorylisthead = pls->memorylist + n / 2;
+        pls->memorylistend  = pls->memorylist + n;
+    }
+    //store the memory in the memory list
+    pls->memorylisthead = mem;
+    ++pls->memorylisthead;
+
+    return mem;
+}
+
+//Free some memory previously allocated by plmalloc or plrealloc and
+//remove it's entry from the PLStream memory list
+void
+plfree( PLStream *pls, void *mem )
+{
+    void *swap     = NULL;
+    void **current = pls->memorylisthead - 1;
+
+    //do nothing for a null pointer
+    if ( !mem )
+        return;
+
+    //the memory list is marked with null at each API entry call. Search
+    //back to the previous null for the memory that we are freeing.
+    //As we move down we shuffle
+    while ( *current )
+    {
+        void * temp = *current;
+        *current = swap;
+        swap     = temp;
+        if ( swap == mem )
+        {
+            free( mem );
+            --pls->memorylisthead;
+            return;
+        }
+    }
+
+    //if we get to here then it means that we did not find
+    //the memory in the list before we reached a NULL. This
+    //is a bug. Because we have shuffled all the pointers
+    //along we need to stick the final one back on, then
+    //then report the problem. We also free the memory, but
+    //maybe we could change this.
+    *( pls->memorylisthead - 1 ) = swap;
+    free( mem );
+    plexit( "Attempted to free a managed buffer that doesn't exist or isn't being managed." );
+}
+
+//Free all memory allocations since the last call to plinitialisememorylist
+//and remove the NULL item marking API entry
+void
+plfreeall( PLStream *pls )
+{
+    --pls->memorylisthead;
+    while ( *pls->memorylisthead )
+    {
+        free( pls->memorylisthead );
+        --pls->memorylisthead;
+    }
+}
+
+//Reallocate memory previously allocated by plmalloc or plrealloc and
+//store it in the memory list
+void *
+plrealloc( PLStream *pls, void *mem, size_t size )
+{
+    void *temp;
+    void **current = pls->memorylisthead - 1;
+    while ( *current && *current != mem )
+        --current;
+    if ( !current )
+        plexit( "Attempted to realloc a managed buffer that doesn't exist or isn't being managed." );
+    temp = realloc( mem, size );
+    if ( !temp )
+        plexit( "Memory allocation failure in plrealloc." );
+    *current = temp;
+    return temp;
+}
+
 //--------------------------------------------------------------------------
 // Driver Interface
 //
@@ -1757,6 +1882,7 @@ pldip2dc( PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax )
 void
 c_plsdiplt( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
 {
+    plinitialisememorylist( plsc );
     plsc->dipxmin = ( xmin < xmax ) ? xmin : xmax;
     plsc->dipxmax = ( xmin < xmax ) ? xmax : xmin;
     plsc->dipymin = ( ymin < ymax ) ? ymin : ymax;
@@ -1770,6 +1896,7 @@ c_plsdiplt( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
 
     plsc->difilt |= PLDI_PLT;
     pldi_ini();
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -1781,6 +1908,7 @@ c_plsdiplt( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
 void
 c_plsdiplz( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
 {
+    plinitialisememorylist( plsc );
     if ( plsc->difilt & PLDI_PLT )
     {
         xmin = plsc->dipxmin + ( plsc->dipxmax - plsc->dipxmin ) * xmin;
@@ -1790,6 +1918,7 @@ c_plsdiplz( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
     }
 
     plsdiplt( xmin, ymin, xmax, ymax );
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -1806,6 +1935,7 @@ c_plsdiplz( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
 static void
 calc_diplt( void )
 {
+    plinitialisememorylist( plsc );
     PLINT pxmin, pxmax, pymin, pymax, pxlen, pylen;
 
     if ( plsc->dev_di )
@@ -1847,10 +1977,12 @@ calc_diplt( void )
 void
 c_plgdiplt( PLFLT *p_xmin, PLFLT *p_ymin, PLFLT *p_xmax, PLFLT *p_ymax )
 {
+    plinitialisememorylist( plsc );
     *p_xmin = plsc->dipxmin;
     *p_xmax = plsc->dipxmax;
     *p_ymin = plsc->dipymin;
     *p_ymax = plsc->dipymax;
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -1867,6 +1999,7 @@ c_plgdiplt( PLFLT *p_xmin, PLFLT *p_ymin, PLFLT *p_xmax, PLFLT *p_ymax )
 void
 c_plsdidev( PLFLT mar, PLFLT aspect, PLFLT jx, PLFLT jy )
 {
+    plinitialisememorylist( plsc );
     plsetvar( plsc->mar, mar );
     plsetvar( plsc->aspect, aspect );
     plsetvar( plsc->jx, jx );
@@ -1881,6 +2014,7 @@ c_plsdidev( PLFLT mar, PLFLT aspect, PLFLT jx, PLFLT jy )
 
     plsc->difilt |= PLDI_DEV;
     pldi_ini();
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -1982,10 +2116,12 @@ calc_didev( void )
 void
 c_plgdidev( PLFLT *p_mar, PLFLT *p_aspect, PLFLT *p_jx, PLFLT *p_jy )
 {
+    plinitialisememorylist( plsc );
     *p_mar    = plsc->mar;
     *p_aspect = plsc->aspect;
     *p_jx     = plsc->jx;
     *p_jy     = plsc->jy;
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -1997,6 +2133,7 @@ c_plgdidev( PLFLT *p_mar, PLFLT *p_aspect, PLFLT *p_jx, PLFLT *p_jy )
 void
 c_plsdiori( PLFLT rot )
 {
+    plinitialisememorylist( plsc );
     plsc->diorot = rot;
     if ( rot == 0. )
     {
@@ -2007,6 +2144,7 @@ c_plsdiori( PLFLT rot )
 
     plsc->difilt |= PLDI_ORI;
     pldi_ini();
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2120,7 +2258,9 @@ calc_diori( void )
 void
 c_plgdiori( PLFLT *p_rot )
 {
+    plinitialisememorylist( plsc );
     *p_rot = plsc->diorot;
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2136,6 +2276,7 @@ void
 c_plsdimap( PLINT dimxmin, PLINT dimxmax, PLINT dimymin, PLINT dimymax,
             PLFLT dimxpmm, PLFLT dimypmm )
 {
+    plinitialisememorylist( plsc );
     plsetvar( plsc->dimxmin, dimxmin );
     plsetvar( plsc->dimxmax, dimxmax );
     plsetvar( plsc->dimymin, dimymin );
@@ -2145,6 +2286,7 @@ c_plsdimap( PLINT dimxmin, PLINT dimxmax, PLINT dimymin, PLINT dimymax,
 
     plsc->difilt |= PLDI_MAP;
     pldi_ini();
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2205,6 +2347,7 @@ calc_dimap()
 void
 c_plflush( void )
 {
+    plinitialisememorylist( plsc );
     if ( plsc->dev_flush )
     {
         char *save_locale = plsave_set_locale();
@@ -2220,6 +2363,7 @@ c_plflush( void )
         if ( plsc->OutFile != NULL )
             fflush( plsc->OutFile );
     }
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2261,6 +2405,7 @@ pllib_init()
 void
 c_plstar( PLINT nx, PLINT ny )
 {
+    plinitialisememorylist( plsc );
     pllib_init();
 
     if ( plsc->level != 0 )
@@ -2269,6 +2414,7 @@ c_plstar( PLINT nx, PLINT ny )
     plssub( nx, ny );
 
     c_plinit();
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2280,6 +2426,7 @@ c_plstar( PLINT nx, PLINT ny )
 void
 c_plstart( PLCHAR_VECTOR devname, PLINT nx, PLINT ny )
 {
+    plinitialisememorylist( plsc );
     pllib_init();
 
     if ( plsc->level != 0 )
@@ -2289,6 +2436,7 @@ c_plstart( PLCHAR_VECTOR devname, PLINT nx, PLINT ny )
     plsdev( devname );
 
     c_plinit();
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2302,6 +2450,7 @@ c_plinit( void )
 {
     PLFLT lx, ly, xpmm_loc, ypmm_loc, aspect_old, aspect_new;
 
+    plinitialisememorylist( plsc );
     pllib_init();
 
     if ( plsc->level != 0 )
@@ -2451,6 +2600,7 @@ c_plinit( void )
 
     plP_gpixmm( &xpmm_loc, &ypmm_loc );
     plP_setpxl( xpmm_loc * plsc->caspfactor, ypmm_loc / plsc->caspfactor );
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2555,6 +2705,8 @@ c_plend1( void )
         free_mem( plsc->plserver );
     if ( plsc->auto_path )
         free_mem( plsc->auto_path );
+    if ( plsc->memorylist )
+        free_mem( plsc->memorylist );
 
     if ( plsc->arrow_x )
         free_mem( plsc->arrow_x );
@@ -2630,7 +2782,9 @@ c_plsstrm( PLINT strm )
 void
 c_plgstrm( PLINT *p_strm )
 {
+    plinitialisememorylist( plsc );
     *p_strm = ipls;
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -2739,6 +2893,7 @@ pl_cpcolor( PLColor *to, PLColor *from )
 void
 c_plcpstrm( PLINT iplsr, PLINT flags )
 {
+    plinitialisememorylist( plsc );
     int      i;
     PLStream *plsr;
 
@@ -2826,6 +2981,7 @@ c_plcpstrm( PLINT iplsr, PLINT flags )
 
     if ( plsc->level == 0 )
         plinit();
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -3466,6 +3622,7 @@ plLoadDriver( void )
 void
 c_plfontld( PLINT ifont )
 {
+    plinitialisememorylist( plsc );
     if ( ifont != 0 )
         ifont = 1;
 
@@ -3473,6 +3630,7 @@ c_plfontld( PLINT ifont )
         plfntld( ifont );
     else
         initfont = ifont;
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -3484,6 +3642,7 @@ c_plfontld( PLINT ifont )
 void
 c_plreplot( void )
 {
+    plinitialisememorylist( plsc );
     if ( plsc->plbuf_buffer != NULL )
     {
         plRemakePlot( plsc );
@@ -3492,6 +3651,7 @@ c_plreplot( void )
     {
         plwarn( "plreplot: plot buffer not available" );
     }
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -3558,12 +3718,14 @@ void
 c_plgpage( PLFLT *p_xp, PLFLT *p_yp,
            PLINT *p_xleng, PLINT *p_yleng, PLINT *p_xoff, PLINT *p_yoff )
 {
+    plinitialisememorylist( plsc );
     *p_xp    = plsc->xdpi;
     *p_yp    = plsc->ydpi;
     *p_xleng = plsc->xlength;
     *p_yleng = plsc->ylength;
     *p_xoff  = plsc->xoffset;
     *p_yoff  = plsc->yoffset;
+    plfreeall( plsc );
 }
 
 // Set output device parameters.  Usually ignored by the driver.
@@ -3571,6 +3733,7 @@ c_plgpage( PLFLT *p_xp, PLFLT *p_yp,
 void
 c_plspage( PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff )
 {
+    plinitialisememorylist( plsc );
     if ( plsc->level > 0 )
         plwarn( "calling plspage() after plinit() may give unpredictable results" );
 
@@ -3588,6 +3751,7 @@ c_plspage( PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff
         plsc->xoffset = xoff;
     if ( yoff )
         plsc->yoffset = yoff;
+    plfreeall( plsc );
 }
 
 // Set the number of subwindows in x and y
@@ -3595,6 +3759,7 @@ c_plspage( PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff
 void
 c_plssub( PLINT nx, PLINT ny )
 {
+    plinitialisememorylist( plsc );
     if ( nx > 0 )
         plsc->nsubx = nx;
     if ( ny > 0 )
@@ -3611,6 +3776,7 @@ c_plssub( PLINT nx, PLINT ny )
     //write the sub pages to the buffer if required
     if ( plsc->plbuf_write )
         plbuf_ssub( plsc );
+    plfreeall( plsc );
 }
 
 // Set the device (keyword) name
@@ -3618,6 +3784,7 @@ c_plssub( PLINT nx, PLINT ny )
 void
 c_plsdev( PLCHAR_VECTOR devname )
 {
+    plinitialisememorylist( plsc );
     if ( plsc->level > 0 )
     {
         plwarn( "plsdev: Must be called before plinit." );
@@ -3628,6 +3795,7 @@ c_plsdev( PLCHAR_VECTOR devname )
         strncpy( plsc->DevName, devname, sizeof ( plsc->DevName ) - 1 );
         plsc->DevName[sizeof ( plsc->DevName ) - 1] = '\0';
     }
+    plfreeall( plsc );
 }
 
 // Get the current device (keyword) name
@@ -3636,7 +3804,9 @@ c_plsdev( PLCHAR_VECTOR devname )
 void
 c_plgdev( char *p_dev )
 {
+    plinitialisememorylist( plsc );
     strcpy( p_dev, plsc->DevName );
+    plfreeall( plsc );
 }
 
 // Set the memory area to be plotted (with the 'mem' driver) as the 'dev'
@@ -3651,9 +3821,11 @@ c_plgdev( char *p_dev )
 void
 c_plsmem( PLINT maxx, PLINT maxy, void *plotmem )
 {
+    plinitialisememorylist( plsc );
     plsc->dev           = plotmem;
     plsc->dev_mem_alpha = 0;
     plP_setphy( 0, maxx, 0, maxy );
+    plfreeall( plsc );
 }
 
 // Same as plsmem, but the buffer is (Y, X, RGBA)
@@ -3661,9 +3833,11 @@ c_plsmem( PLINT maxx, PLINT maxy, void *plotmem )
 void
 c_plsmema( PLINT maxx, PLINT maxy, void *plotmem )
 {
+    plinitialisememorylist( plsc );
     plsc->dev           = plotmem;
     plsc->dev_mem_alpha = 1;
     plP_setphy( 0, maxx, 0, maxy );
+    plfreeall( plsc );
 }
 
 // Get the current stream pointer
@@ -3685,7 +3859,9 @@ plgpls( PLStream **p_pls )
 void
 c_plglevel( PLINT *p_level )
 {
+    plinitialisememorylist( plsc );
     *p_level = plsc->level;
+    plfreeall( plsc );
 }
 
 // Set the function pointer for the keyboard event handler
@@ -3743,7 +3919,9 @@ plsError( PLINT *errcode, char *errmsg )
 void
 c_plsori( PLINT ori )
 {
+    plinitialisememorylist( plsc );
     plsdiori( (PLFLT) ori );
+    plfreeall( plsc );
 }
 
 //
@@ -3755,6 +3933,7 @@ c_plsori( PLINT ori )
 void
 c_plwidth( PLFLT width )
 {
+    plinitialisememorylist( plsc );
     if ( width != plsc->width && width >= 0. )
     {
         plsc->width = width;
@@ -3765,6 +3944,7 @@ c_plwidth( PLFLT width )
                 plP_state( PLSTATE_WIDTH );
         }
     }
+    plfreeall( plsc );
 }
 
 // Set the output file pointer
@@ -3789,6 +3969,7 @@ plsfile( FILE *file )
 void
 c_plgfnam( char *fnam )
 {
+    plinitialisememorylist( plsc );
     if ( fnam == NULL )
     {
         plabort( "filename string must be preallocated to >=80 bytes" );
@@ -3801,6 +3982,7 @@ c_plgfnam( char *fnam )
         strncpy( fnam, plsc->FileName, 79 );
         fnam[79] = '\0';
     }
+    plfreeall( plsc );
 }
 
 // Set the output file name.
@@ -3808,7 +3990,9 @@ c_plgfnam( char *fnam )
 void
 c_plsfnam( PLCHAR_VECTOR fnam )
 {
+    plinitialisememorylist( plsc );
     plP_sfnam( plsc, fnam );
+    plfreeall( plsc );
 }
 
 // Set the pointer to the data used in driver initialisation
@@ -3830,7 +4014,9 @@ plsdevdata( void *data )
 void
 c_plspause( PLINT p )
 {
+    plinitialisememorylist( plsc );
     plsc->nopause = !p;
+    plfreeall( plsc );
 }
 
 // Set the floating point precision (in number of places) in numeric labels.
@@ -3838,8 +4024,10 @@ c_plspause( PLINT p )
 void
 c_plprec( PLINT setp, PLINT prec )
 {
+    plinitialisememorylist( plsc );
     plsc->setpre = setp;
     plsc->precis = prec;
+    plfreeall( plsc );
 }
 
 // Get the floating point precision (in number of places) in numeric labels.
@@ -3868,6 +4056,7 @@ plP_gtimefmt()
 void
 c_plsesc( char esc )
 {
+    plinitialisememorylist( plsc );
     switch ( esc )
     {
     case '!':                   // ASCII 33
@@ -3885,6 +4074,7 @@ c_plsesc( char esc )
     default:
         plwarn( "plsesc: Invalid escape character, ignoring." );
     }
+    plfreeall( plsc );
 }
 
 // Get the escape character for text strings.
@@ -3904,8 +4094,10 @@ plgesc( char *p_esc )
 void
 c_plsfci( PLUNICODE fci )
 {
+    plinitialisememorylist( plsc );
     // Always mark FCI as such.
     plsc->fci = fci | PL_FCI_MARK;
+    plfreeall( plsc );
 }
 
 // Get the FCI (font characterization integer) for unicode-enabled device
@@ -3914,8 +4106,10 @@ c_plsfci( PLUNICODE fci )
 void
 c_plgfci( PLUNICODE *p_fci )
 {
+    plinitialisememorylist( plsc );
     // Always mark FCI as such.
     *p_fci = plsc->fci | PL_FCI_MARK;
+    plfreeall( plsc );
 }
 // Store hex digit value shifted to the left by hexdigit hexadecimal digits
 // into pre-existing FCI.
@@ -3948,7 +4142,9 @@ plP_fci2hex( PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower )
 void
 c_plgver( char *p_ver )
 {
+    plinitialisememorylist( plsc );
     strcpy( p_ver, PLPLOT_VERSION );
+    plfreeall( plsc );
 }
 
 // Set inferior X window
@@ -3973,9 +4169,11 @@ plsxwin( PLINT window_id )
 void
 c_plgfam( PLINT *p_fam, PLINT *p_num, PLINT *p_bmax )
 {
+    plinitialisememorylist( plsc );
     *p_fam  = plsc->family;
     *p_num  = plsc->member;
     *p_bmax = plsc->bytemax;
+    plfreeall( plsc );
 }
 
 // Set family file parameters
@@ -3983,6 +4181,7 @@ c_plgfam( PLINT *p_fam, PLINT *p_num, PLINT *p_bmax )
 void
 c_plsfam( PLINT fam, PLINT num, PLINT bmax )
 {
+    plinitialisememorylist( plsc );
     if ( plsc->level > 0 )
         plwarn( "plsfam: Must be called before plinit." );
 
@@ -3992,6 +4191,7 @@ c_plsfam( PLINT fam, PLINT num, PLINT bmax )
         plsc->member = num;
     if ( bmax >= 0 )
         plsc->bytemax = bmax;
+    plfreeall( plsc );
 }
 
 // Advance to the next family file on the next new page
@@ -3999,7 +4199,9 @@ c_plsfam( PLINT fam, PLINT num, PLINT bmax )
 void
 c_plfamadv( void )
 {
+    plinitialisememorylist( plsc );
     plsc->famadv = 1;
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -4012,8 +4214,10 @@ c_plfamadv( void )
 void
 c_plgxax( PLINT *p_digmax, PLINT *p_digits )
 {
+    plinitialisememorylist( plsc );
     *p_digmax = plsc->xdigmax;
     *p_digits = plsc->xdigits;
+    plfreeall( plsc );
 }
 
 // Set x axis labeling parameters
@@ -4021,8 +4225,10 @@ c_plgxax( PLINT *p_digmax, PLINT *p_digits )
 void
 c_plsxax( PLINT digmax, PLINT digits )
 {
+    plinitialisememorylist( plsc );
     plsc->xdigmax = digmax;
     plsc->xdigits = digits;
+    plfreeall( plsc );
 }
 
 // Get y axis labeling parameters
@@ -4030,8 +4236,10 @@ c_plsxax( PLINT digmax, PLINT digits )
 void
 c_plgyax( PLINT *p_digmax, PLINT *p_digits )
 {
+    plinitialisememorylist( plsc );
     *p_digmax = plsc->ydigmax;
     *p_digits = plsc->ydigits;
+    plfreeall( plsc );
 }
 
 // Set y axis labeling parameters
@@ -4039,8 +4247,10 @@ c_plgyax( PLINT *p_digmax, PLINT *p_digits )
 void
 c_plsyax( PLINT digmax, PLINT digits )
 {
+    plinitialisememorylist( plsc );
     plsc->ydigmax = digmax;
     plsc->ydigits = digits;
+    plfreeall( plsc );
 }
 
 // Get z axis labeling parameters
@@ -4048,8 +4258,10 @@ c_plsyax( PLINT digmax, PLINT digits )
 void
 c_plgzax( PLINT *p_digmax, PLINT *p_digits )
 {
+    plinitialisememorylist( plsc );
     *p_digmax = plsc->zdigmax;
     *p_digits = plsc->zdigits;
+    plfreeall( plsc );
 }
 
 // Set z axis labeling parameters
@@ -4057,8 +4269,10 @@ c_plgzax( PLINT *p_digmax, PLINT *p_digits )
 void
 c_plszax( PLINT digmax, PLINT digits )
 {
+    plinitialisememorylist( plsc );
     plsc->zdigmax = digmax;
     plsc->zdigits = digits;
+    plfreeall( plsc );
 }
 
 // Get character default height and current (scaled) height
@@ -4066,8 +4280,10 @@ c_plszax( PLINT digmax, PLINT digits )
 void
 c_plgchr( PLFLT *p_def, PLFLT *p_ht )
 {
+    plinitialisememorylist( plsc );
     *p_def = plsc->chrdef;
     *p_ht  = plsc->chrht;
+    plfreeall( plsc );
 }
 
 // Get viewport boundaries in normalized device coordinates
@@ -4075,10 +4291,12 @@ c_plgchr( PLFLT *p_def, PLFLT *p_ht )
 void
 c_plgvpd( PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax )
 {
+    plinitialisememorylist( plsc );
     *p_xmin = plsc->vpdxmi;
     *p_xmax = plsc->vpdxma;
     *p_ymin = plsc->vpdymi;
     *p_ymax = plsc->vpdyma;
+    plfreeall( plsc );
 }
 
 // Get viewport boundaries in world coordinates
@@ -4086,10 +4304,12 @@ c_plgvpd( PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax )
 void
 c_plgvpw( PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax )
 {
+    plinitialisememorylist( plsc );
     *p_xmin = plsc->vpwxmi;
     *p_xmax = plsc->vpwxma;
     *p_ymin = plsc->vpwymi;
     *p_ymax = plsc->vpwyma;
+    plfreeall( plsc );
 }
 
 // Get the viewport boundaries in world coordinates, expanded slightly
@@ -4248,10 +4468,12 @@ plP_setphy( PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax )
 void
 c_plscompression( PLINT compression )
 {
+    plinitialisememorylist( plsc );
     if ( plsc->level <= 0 )
     {
         plsc->dev_compression = compression;
     }
+    plfreeall( plsc );
 }
 
 //--------------------------------------------------------------------------
@@ -4263,7 +4485,9 @@ c_plscompression( PLINT compression )
 void
 c_plgcompression( PLINT *compression )
 {
+    plinitialisememorylist( plsc );
     *compression = plsc->dev_compression;
+    plfreeall( plsc );
 }
 
 
@@ -4451,6 +4675,8 @@ plP_image( PLFLT *z, PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT
 void
 c_plstransform( PLTRANSFORM_callback coordinate_transform, PLPointer coordinate_transform_data )
 {
+    plinitialisememorylist( plsc );
     plsc->coordinate_transform      = coordinate_transform;
     plsc->coordinate_transform_data = coordinate_transform_data;
+    plfreeall( plsc );
 }
-- 
2.8.3

