I've just been having a look through the plexit calls. 99% of them are to do with memory allocation. I've begun creatin a plxxxarray structure where xxx could be flt, int, char, color etc to try to make memory management easier. The struct will contain the memory itself, the size of the array and a series of function pointers for doing things like resizing, pushing an element to the back, inserting elements etc.

so something like
plfltarray myfloats;
constructplfltarray( &myfloats, 5 );
myfloats.resize( &myfloats, 10 );
for( size_t i = 0; i < myfloats.n; ++i )
   myfloats.mem[i]=(PLFLT) i;
myfloats.destroy( &myfloats );

would declare an array of PLFLTs, construct it, which involves setting the function pointers and an initial size (which could be zero), resize it to 10 elements, assign values to each element, then destroy it freeing the memory.

Unfortunately we can't get automatic constructor and destructor calls like in C++ to deal with memory management, but what we do get is lots of code reuse - so no more if ( arr != NULL ) free( arr ); malloc( newsize*sizeof(type) ).

The most important advantage is probably that we remove the possibility of missing setting the size of an array - particularly if the memory allocation fails. We also get a situation where if an allocation fails then the old data can be retained, meaning that a fail of memory allocation will result in no change, rather than changing an array to NULL. Another advantage is that we can copy the STL and allocate more memory than needed during a resize, so that future resizes don't result in reallocation and copying. Basically all these things make the code more robust in the case of memory allocation failure and make it easier to remove the plexit calls.

However while starting to go through the various arrays in PLStream, I found that in opt_ncol0 plsc->ncol0 is set, but plsc->cmap0 isn't resized to match. To me this seems rather dangerous and certainly violates the principle of least surprise. Such a situation wouldn't be permitted in the above model where plsc->cmap0 would be a plcolorarray and plsc->cmap0.n would replace plsc->ncol0. Before I change it I wanted to check if anyone knew a good reason why things are coded this way?


From: Phil Rosenberg <philip_rosenberg@yahoo.com>
To: Hezekiah M. Carty <hezekiahcarty@users.sourceforge.net>; Hazen Babcock <hbabcock@mac.com>
Cc: "plplot-devel@lists.sourceforge.net" <plplot-devel@lists.sourceforge.net>
Sent: Saturday, 16 August 2014, 15:17
Subject: RE: [Plplot-devel] exit() calls

Okay, well that seems like a quorum then. I'll start putting it into action.

Interesting that for Cairo it says it is safe to use an object if in error state. Wonder if errors get cleared at any point.

From: Hezekiah M. Carty
Sent: ‎16/‎08/‎2014 12:09
To: Hazen Babcock
Cc: Phil Rosenberg; plplot-devel@lists.sourceforge.net
Subject: Re: [Plplot-devel] exit() calls

On Fri, Aug 15, 2014 at 8:55 PM, Hazen Babcock <hbabcock@mac.com> wrote:
> On 8/14/2014 6:00 PM, Phil Rosenberg wrote:
>> Hi Hazen
>> The approach of just don't call exit and see what happens was also my first thought. Then the first case i looked at was plscmap0n, which attempts to set the number of colours in cmap0, this is called by plspal0, which immediately assumes the call has succeeded and attempts to assign colours to cmap0. If the malloc call actually failed, then the memory is set to null and we'll get a segfault.
> I guess I favor an opt-in rather than the current opt-out strategy for
> plexit(). However it is true that both are going to land you in the same
> place, unless you have a special error handler your program is going to
> crash with a (possibly cryptic) error message.
> At this point I agree with you that adding an error flag to the stream
> which the user can check is the way to go. Changing all the functions in
> all the bindings would be extremely disruptive.
> Cairo and GTK are C I believe, it might be worth a look to see how they
> handle this.

This seems to be roughly equivalent to how Cairo handles errors:


This would be a nice change for plabort calls as well.  It would allow
(relatively) safe programmatic access to error information which would
be particularly useful for language bindings which may want to
translate these error states into an exception, special return value
or other language-appropriate response.