Possible compiler bug with this simple program

This is a discussion on Possible compiler bug with this simple program within the ADA forums in Programming Languages category; On Sep 3, 7:20*am, Adam Beneschan <a...@irvine.com> wrote: > > Several of us have pointed out that it's a bad idea to use an > unconstrained array type (i.e. Real_Vector) as a parameter to an > imported routine (or a routine with convention C), but the above code > still did it. > > * * * * * * * * * * * * * * * -- Adam In about a hundred cases in this same binding project, I have passed an unconstrained array (and its length) as a parameter to an Imported C subprogram without consequence--no ...

Go Back   Application Development Forum > Programming Languages > ADA

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #21  
Old 09-03-2008, 08:22 PM
Jerry
Guest
 
Default Re: Possible compiler bug with this simple program

On Sep 3, 7:20*am, Adam Beneschan <a...@irvine.com> wrote:
>
> Several of us have pointed out that it's a bad idea to use an
> unconstrained array type (i.e. Real_Vector) as a parameter to an
> imported routine (or a routine with convention C), but the above code
> still did it.
>
> * * * * * * * * * * * * * * * -- Adam


In about a hundred cases in this same binding project, I have passed
an unconstrained array (and its length) as a parameter to an Imported
C subprogram without consequence--no warnings, no errors, no hangs--on
several kinds of machines (32-bit and 64-bit). This seems to be
allowed by ARM B.3.70: "An Ada parameter of an array type with
component type T, of any mode, is passed as a t* argument to a C
function, where t is the C type corresponding to the Ada type T."
There is no restriction on unconstrained array types.

The reason that I posted the modified code (mixed Ada and C) is that
Randy's post indicated that it should work.

In one instance (of the "hundred"), I "rename" one of these Imported C
subprograms (it has two unconstrained arrays and their length as
parameters). At the point of the "rename," GNAT generates two
warnings, "foreign caller must pass bounds explicitly," and "type of
argument "plfill.y" is unconstrained array." (plfill is the procedure
name and y is one of the unconstrained arrays. A similar pair of
warnings is generated for the other passed unconstrained array.) The
purpose for renaming the procedure, which is originally declared as an
Import with C conventions in another package (without warnings), is to
allow the user to pass it as a callback to another Imported C
subprogram. This works without problems.

The difference between the two cases ([1] described above, herein, and
[2] the code in mixed Ada and C that I posted earlier), is that in
[1], both the called procedure and the callback procedure are written
in C, and the in problematic code [2], the called subprogram is in C
(plmap) but the callback (mapform19) is written in Ada, with C
conventions.

In a third scenario in the binding project [3], Ada successfully calls
an Imported procedure written in C and passes a callback written in
Ada with C conventions; this closely resembles the problematic code
[2] except that in [3], the callback function is passed with 'Access
and in [2] it is passed with 'Unrestricted_Access. Also, [3] doesn't
pass an unconstrained array. (I don't see how to make [2] work with
'access without requiring the user to put the user-written callback
into the binding package.)

Jerry
Reply With Quote
  #22  
Old 09-03-2008, 09:18 PM
Adam Beneschan
Guest
 
Default Re: Possible compiler bug with this simple program

On Sep 3, 5:22 pm, Jerry <lancebo...@qwest.net> wrote:
> On Sep 3, 7:20 am, Adam Beneschan <a...@irvine.com> wrote:
>
>
>
> > Several of us have pointed out that it's a bad idea to use an
> > unconstrained array type (i.e. Real_Vector) as a parameter to an
> > imported routine (or a routine with convention C), but the above code
> > still did it.

>
> > -- Adam

>
> In about a hundred cases in this same binding project, I have passed
> an unconstrained array (and its length) as a parameter to an Imported
> C subprogram without consequence--no warnings, no errors, no hangs--on
> several kinds of machines (32-bit and 64-bit). This seems to be
> allowed by ARM B.3.70: "An Ada parameter of an array type with
> component type T, of any mode, is passed as a t* argument to a C
> function, where t is the C type corresponding to the Ada type T."
> There is no restriction on unconstrained array types.


This talks about passing an unconstrained array parameter *from* an
Ada routine *to* a C function. You're doing more than that---you're
having the C function pass the unconstrained array parameter back *to*
an Ada routine, which the manual says nothing about.


> The reason that I posted the modified code (mixed Ada and C) is that
> Randy's post indicated that it should work.


I think there must be a misunderstanding. In one of his posts he
seemed to imply that it should work to pass an unconstrained array
parameter to a C routine on all Ada compilers, but he then referred to
the program as "unportable garbage". In another post he said that
either the Ada compiler should document what should happen when an
unconstrained array parameter is passed from C to Ada and implement it
that way consistently (e.g. it should just decree that the lower bound
is 0 and document it that way---but that's just one possible way of
handling it), or reject the program. GNAT apparently doesn't do
either so it's defective. The bug in GNAT, I believe, is that it
compiles your Ada program in the first place---just my opinion.


> In one instance (of the "hundred"), I "rename" one of these Imported C
> subprograms (it has two unconstrained arrays and their length as
> parameters). At the point of the "rename," GNAT generates two
> warnings, "foreign caller must pass bounds explicitly," and "type of
> argument "plfill.y" is unconstrained array." (plfill is the procedure
> name and y is one of the unconstrained arrays. A similar pair of
> warnings is generated for the other passed unconstrained array.) The
> purpose for renaming the procedure, which is originally declared as an
> Import with C conventions in another package (without warnings), is to
> allow the user to pass it as a callback to another Imported C
> subprogram. This works without problems.
>
> The difference between the two cases ([1] described above, herein, and
> [2] the code in mixed Ada and C that I posted earlier), is that in
> [1], both the called procedure and the callback procedure are written
> in C, and the in problematic code [2], the called subprogram is in C
> (plmap) but the callback (mapform19) is written in Ada, with C
> conventions.


Yup, this is not surprising at all to me. And if you go back and
reread my earlier post, I believe I explained pretty thoroughly why
this is happening, and also gave you a solution. Don't use an
unconstrained array type in your callback routine. Period. You can
use unconstrained arrays when calling C routines from Ada; but if
you're going to call Ada routines from C, don't.

-- Adam


Reply With Quote
  #23  
Old 09-03-2008, 09:31 PM
Jeffrey R. Carter
Guest
 
Default Re: Possible compiler bug with this simple program

Jerry wrote:
>
> In about a hundred cases in this same binding project, I have passed
> an unconstrained array (and its length) as a parameter to an Imported
> C subprogram without consequence--no warnings, no errors, no hangs--on
> several kinds of machines (32-bit and 64-bit). This seems to be
> allowed by ARM B.3.70: "An Ada parameter of an array type with
> component type T, of any mode, is passed as a t* argument to a C
> function, where t is the C type corresponding to the Ada type T."
> There is no restriction on unconstrained array types.


Yes, but you're passing a pointer to an Ada convention-C subprogram to a C
function, and C is calling that subprogram. The subprogram has a an
unconstrained array parameter. This says nothing about what happens when C calls
Ada.

Ada needs to know what the lower bound of this array parameter is, and
apparently your compiler is getting it wrong. Using a constrained array type
with a lower bound of zero and an upper bound as large or larger than can occur
would be the best choice for this situation.

--
Jeff Carter
"I fart in your general direction."
Monty Python & the Holy Grail
05
Reply With Quote
  #24  
Old 09-03-2008, 11:53 PM
Randy Brukardt
Guest
 
Default Re: Possible compiler bug with this simple program

"Adam Beneschan" <adam@irvine.com> wrote in message
news:90006a35-e933-40f1-9a76-5698b0ce75d1@s20g2000prd.googlegroups.com...
....
>> The difference between the two cases ([1] described above, herein, and
>> [2] the code in mixed Ada and C that I posted earlier), is that in
>> [1], both the called procedure and the callback procedure are written
>> in C, and the in problematic code [2], the called subprogram is in C
>> (plmap) but the callback (mapform19) is written in Ada, with C
>> conventions.

>
> Yup, this is not surprising at all to me. And if you go back and
> reread my earlier post, I believe I explained pretty thoroughly why
> this is happening, and also gave you a solution. Don't use an
> unconstrained array type in your callback routine. Period. You can
> use unconstrained arrays when calling C routines from Ada; but if
> you're going to call Ada routines from C, don't.


Right. It is *only* OK to use an unconstrained array parameter in a
subprogram that has pragma Import. It is *not* OK in any other context for C
(objects, subprograms with Convention or Export pragmas, function returns of
any kind). Your program is still using pragma Convention and you are still
having C call Ada with an unconstrained parameter. You can't do that
portably.

I may have not looked carefully enough at your original program; I presumed
that reason you were using pragma Convention was so that you could write the
routine in Ada, and that it would be replaced by pragma Import in the real
program. If that was wrong, I probably mislead you.

Randy.


Reply With Quote
  #25  
Old 09-04-2008, 10:35 AM
Adam Beneschan
Guest
 
Default Re: Possible compiler bug with this simple program

On Sep 3, 6:31 pm, "Jeffrey R. Carter"
<spam.jrcarter....@spam.acm.org> wrote:

> Ada needs to know what the lower bound of this array parameter is, and
> apparently your compiler is getting it wrong.


One other thing that probably ought to be mentioned: It's possible
that the compiler is trying to determine the lower bound by looking at
some memory location where it expects the lower bound to be, but in
reality (since the Ada routine is being called from C) contains a
random value previously used for something else. My experience is
that memory locations with random values contain zero a high
percentage of the time, so it would make sense that the program would
happen to work on some platforms, or on some targets. If I understood
the original post correctly, the program seemed to be working on some
platforms but not others, and it could well be because of this random
factor. It doesn't mean the compiler or the program were correct on
those platforms.


> Using a constrained array type


or subtype, I think.


> with a lower bound of zero and an upper bound as large or larger than can occur
> would be the best choice for this situation.


-- Adam
Reply With Quote
  #26  
Old 09-04-2008, 10:42 AM
Jacob Sparre Andersen
Guest
 
Default Re: Possible compiler bug with this simple program

[ calling an Ada function from C with an array argument ]

Isn't this a case, where package Interfaces.C.Pointers is appropriate
to use? (Despite the name, it seems mostly to be concerned with
C-style "arrays".)

Greetings,

Jacob
--
"Never trust a statistic you have not falsified yourself."
Reply With Quote
  #27  
Old 09-04-2008, 04:49 PM
Simon Wright
Guest
 
Default Re: Possible compiler bug with this simple program

Jerry <lanceboyle@qwest.net> writes:

> The difference between the two cases ([1] described above, herein, and
> [2] the code in mixed Ada and C that I posted earlier), is that in
> [1], both the called procedure and the callback procedure are written
> in C, and the in problematic code [2], the called subprogram is in C
> (plmap) but the callback (mapform19) is written in Ada, with C
> conventions.


Referring to [2], you also need to be careful (GNAT & VxWorks at least)
if the C calling thread isn't an Ada task; the Ada code expects the
VxWorks TCB to contain a pointer to auxiliary Ada RTS structures.

Call GNAT.Threads.Register_Thread (as early as possible in the called
Ada subprogram, I guess! before it needs the secondary stack, for
example)
Reply With Quote
  #28  
Old 09-05-2008, 04:17 AM
Ludovic Brenta
Guest
 
Default Re: Possible compiler bug with this simple program

Jeff Carter writes:
> Ada needs to know what the lower bound of this array parameter is, and
> apparently your compiler is getting it wrong. Using a constrained array type
> with a lower bound of zero and an upper bound as large or larger than can occur
> would be the best choice for this situation.


I would actually use a local, constrained array type of exactly the
required length:

procedure Ada_Callback (Length : in Natural; Array_Address : in
System.Address);
pragma Convention (C, Ada_Callback);

procedure Ada_Callback (Length : in Natural; Array_Address : in
System.Address) is
type Constrained_Array_Subtype is array (1 .. Length) of
Long_Float;
X : Constrained_Array_Subtype;
for X'Address use Array_Address;
pragma Import (Ada, X); -- disable default initialization
begin
...
end Ada_Callback;

I know using System.Address may seem unholy at first sight but this
implementation is explicit about what it does -- dangerous things with
an address received from the unsafe "external world" outside the
control of the compiler.

Comments?

--
Ludovic Brenta.
Reply With Quote
  #29  
Old 09-05-2008, 11:56 AM
Adam Beneschan
Guest
 
Default Re: Possible compiler bug with this simple program

On Sep 5, 1:17 am, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
> Jeff Carter writes:
> > Ada needs to know what the lower bound of this array parameter is, and
> > apparently your compiler is getting it wrong. Using a constrained array type
> > with a lower bound of zero and an upper bound as large or larger than can occur
> > would be the best choice for this situation.

>
> I would actually use a local, constrained array type of exactly the
> required length:
>
> procedure Ada_Callback (Length : in Natural; Array_Address : in
> System.Address);
> pragma Convention (C, Ada_Callback);
>
> procedure Ada_Callback (Length : in Natural; Array_Address : in
> System.Address) is
> type Constrained_Array_Subtype is array (1 .. Length) of
> Long_Float;


or array (0 .. Length - 1)...


> X : Constrained_Array_Subtype;
> for X'Address use Array_Address;
> pragma Import (Ada, X); -- disable default initialization
> begin
> ...
> end Ada_Callback;
>
> I know using System.Address may seem unholy at first sight but this
> implementation is explicit about what it does -- dangerous things with
> an address received from the unsafe "external world" outside the
> control of the compiler.
>
> Comments?


Doing it your way has a better chance of being portable. Earlier,
others and I have recommended using a constrained array subtype (with
a large upper bound) as a parameter, and I'd guess that will have the
desired effect on most compilers, but you never know---sometimes
compilers have unexpected ways of doing things. If you're sure that a
System.Address will look just like a C (void *) or (double *) type,
and will be passed in the same way, then using a System.Address
parameter will make pretty sure that things will work right.

-- Adam


Reply With Quote
  #30  
Old 09-05-2008, 01:09 PM
Jeffrey R. Carter
Guest
 
Default Re: Possible compiler bug with this simple program

Ludovic Brenta wrote:
>
> I know using System.Address may seem unholy at first sight but this
> implementation is explicit about what it does -- dangerous things with
> an address received from the unsafe "external world" outside the
> control of the compiler.
>
> Comments?


There's no guarantee that a C pointer and Ada's System.Address are the same
thing. Of course, to be safe, you shouldn't use Integer, Long_Float, or any
other type not declared in Interfaces.C and its children, or otherwise declared
convention C. So really this should be something like

type Double_Ptr is access all Interfaces.C.Double;
pragma Convention (C, Double_Ptr);

procedure Ada_Callback (Length : Interfaces.C.Int; First_Component : Double_Ptr);
pragma Convention (C, Ada_Callback);

And then mess with pointer arithmetic (:

But a constrained array type is just as safe:

type C_List is array (Interfaces.C.Int range 0 .. Interfaces.C.Int'Last) of
aliased Interfaces.C.Double;
pragma Convention (C, C_List);

procedure Ada_Callback (Length : Interfaces.C.Int; List : C_List);
pragma Convention (C, Ada_Callback);

And much easier to use.

--
Jeff Carter
"You me on the head hitted."
Never Give a Sucker an Even Break
108
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 01:54 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.