This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: allocate() interface (PR30115)


On Fri, Dec 08, 2006 at 09:09:47AM +0100, Richard Guenther wrote:

> void
> allocate_array (void **mem, GFC_INTEGER_4 size, GFC_INTEGER_4 * stat)
> {
>   if (*mem == NULL)
>     {
>       allocate (mem, size, stat);
>       return;
>     }
>   if (stat)
>     {
>       free (*mem);
>       allocate (mem, size, stat);
>       *stat = ERROR_ALLOCATION;
>       return;
>     }
>   else
>     runtime_error ("Attempting to allocate already allocated array.");
> 
>   return;
> }
> 
> so allocating an already allocated array is an error,

It is.

> but we still re-allocate in this case?

There was some discussion a while ago on what to do for

    real, allocatable :: a(:)
    allocate (a(5))
    allocate(a(3), stat=i)

It was thought that the most recent allocation was probably what
the programmer intended, and it would be best to continue in that
way.  This is not required by the standard, though.

>Also, why's *stat set to ERROR_ALLOCATION
> instead of 1 as in the other allocators?

This is not required by the standard, the value is
implementation-defined.

> Is the current interfacing somehow required by the standard or is
> it done the way it is because of history and debugging?  Also we
> seem to emit stuff like
> 
>   size = ...;
>   if (size < 0)
>     size = 0;
>   allocate (..., size, ...);
> 
> why?

Statements like

    allocate (a(1:0))

(which yields a zero size) or

    allocate (a(1:3, 0:-2))

(which would yield a negative size) are required to return a
zero-sized array, which is a well-defined entity in Fortran.

>We check the size argument in the allocators and simply allocate
> 1 byte (!???) in the case we get a zero size argument,

To make the deallocate statement work without special-casing on size
(which would be awkward to re-compute from the array descriptor).

>but will error
> with negative sizes which we catch earlier.

Negative sizes are checked in order to catch integer overflow
(which is something that can happen).

> So my proposed allocate would look like
> 
> static void *
> allocate_size (size_t size, _Bool errorp)
> {
>   void *newmem;
> 
>   newmem = malloc (size);
>   if (!newmem && errorp)
>     runtime_error ("ALLOCATE: Out of memory.");
> 
>   return newmem;
> }
> 
> void *
> allocate (GFC_INTEGER_4 size, GFC_INTEGER_4 errorp)
> {
>   if (size < 0)
>     {
>       runtime_error ("Attempt to allocate negative amount of memory.  "
>                      "Possible integer overflow");
>       abort ();
>     }
> 
>   return allocate_size ((size_t) size, errorp);
> }
> 
> where we would emit calls to allocate like
> 
>  data = allocate (size, errorp);
>  if (!data)
>    ...

This would violate the Fortran standard (because of the
requirement for zero-sized arrays).

> i.e. the previous *stat argument is now a flag to indicate whether
> we need to raise errors, the returned status is done via the memory
> pointer being NULL on errors.  (I don't know in which cases the
> stat pointer is non-NULL now, presumably a user-controlled thing)

stat is non-null if the stat argument is passed to allocate().

> Ideas, thoughts?

This is legal, and required to work:

    real, pointer :: a(:)
    allocate (a(4))
    allocate (a(3))

and this is illegal:

    real, allocatable :: a(:)
    allocate (a(4))
    allocate (a(3))

	Thomas


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]