error handling

shoup at shoup at
Wed Dec 17 15:56:28 UTC 2014

I agree that these global pointers to functions have a number
of problems.

I was going to say that for some situations, it would be better
to have these choices made and compile/link time rather than run time.
But I see from what you say that there are more complex scenarios
to consider...oh well...for these situations that you mention,
one way to deal with them in a way that proovides more
backward compatibility would be to have a global (actually,
thread local) context for all this stuff that a client could
backup and restore (and a C++ client could use RAII for this).

Anyway, just a's pretty ugly, too...

Another observation: your idea for packing "handler info" in GMP
structs would not work for clients (suchy as my own library) that
use GMP only at the mpn-level.  Of course, such clients probably
have less interest in controlling the memory allocation of GMP,
as the only memory to be managed here is the temp space
needed by the mpn-level routines.  However, error handing is
still an issue here.

[ NOTE: you said you moved this from gmp-devel thread, but I hit
reply-all and it seems like I'm posting to this thread...sorry about that ]

On Wed, December 17, 2014 8:49 am, Torbjörn Granlund wrote:
> [Moved thread from gmp-devel.]
> I'd like to think of error handling also in a C perspective, and
> consider a few more problems at the same time.
> Which sources of exceptions do we have currently?
> 1 We divide by 0 to generate a SIGFPE.  I think we do that for division
>   by zero as well as some other mathematically undefined operation.
> 2 We detect overflow of _mp_size.
> 3 Allocation problems.
> 4 Stack overflow leading to SIGSEGV.  (I've recently trimmed the stack
>   usage to stay within a few hundred KiB, but some threaded environment
>   give tiny default stacks.)
> 6 More that I have forgotten.
> I saw the suggestion to invoke a user-defined function instead of the
> explicitly detected errors (i.e., 1, 2, 3, 5, perhaps 6).  That is an
> idea worth considering.  We have function pointers to for allocation,
> reallocation, freeing; this would be one more such global pointer.
> The error handler function would then use the knowledge of the
> allocation functions to clean up the memory state, and probably longjump
> to to deallocate stack.
> GMP might be able to clean up TMP_* memory, since that is a kind of
> stack.
> I am not too fond of these global pointers.  It would be better design
> to refer the memory handling and error handling functions from each GMP
> user variable, akin to object oriented languages' vtables.  Except that
> this would make these small structures 3 times larger.
> There are real scenarios where one would want different sets of
> allocation functions.  E.g., many libraries use GMP.  Some of them have
> their orn error reporting mechanisms, and memory handles.  But then the
> user might use GMP directly, or she might from the same program use
> several libraries which use GMP.  The current GMP memory allocation
> mechanism is not suitable here.
> We have another problem with the GMP structures.  On 64-bit machines,
> the 32-bit _mp_size field is starting to hurt for some applications, and
> with that also the _mp_alloc field.
> We might therefore consider changing these structures in an incompatible
> way.  We culd then sneak in a field for choosing 'handler functions'.
> Perhaps like this:
>         signed long _mp_size     : 46;
>         unsigned long _mp_alloc  : 14;  // 8-bit mantissa, 6-bit exponent
>         unsigned long _mp_handler:  4;
>         mp_limb_t _mp_d;        // 64
> The trickery with field sizes keeps the structure at 128 bits.  There
> will be a cost for it, though.
> The _mp_handler field chooses one of 16 handler groups.  Each such group
> will have function pointers for allocation, reallocation, freeing, and
> error reporting.  I'd say that 16 groups will be sufficient for any use.
> The _mp_alloc alloc field is a home-brew float.  Allocations <= 255 will
> have have field values 1..255 which require no extra processing.
> An alternative _mp_alloc trickery would define the current allocation in
> terms of the _mp_size field, saying how much unused space there is.
> Such a field wouldn't need to be very large, but then there would be
> situation where GMP would need to realloce when an operand decreases a
> lot in size.
> To avoid any of this trickery, we could change the structure to be 192
> bits.  That would cost a lot in cache load for applications which
> e.g. use arrays of GMP numbers.  Like this:
>         signed long _mp_size     : 64;
>         unsigned long _mp_alloc  : 60;
>         unsigned long _mp_handler:  4;
>         mp_limb_t _mp_d;        // 64
> (These sizes are hard to overflow, except for those with lots of time
> and who can afford 8 Eibyte of memory.)
> --
> Torbjörn
> Please encrypt, key id 0xC8601622

More information about the gmp-devel mailing list