comp.lang.ada
 help / color / mirror / Atom feed
* Ada style of passing 'in' parameters considered dangerous?
@ 2003-02-08 22:24 Antti Sykari
  2003-02-09  0:41 ` James S. Rogers
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: Antti Sykari @ 2003-02-08 22:24 UTC (permalink / raw)


Hello,

I recently asked in comp.compilers advice about implementing a
parameter passing policy for a rather close-to-machine language.  My
suggestion for the method of passing 'in' parameters to procedures
was:  Pass everything as readonly by default, and leave the
by-reference/by-copy decision to the compiler.

It was pointed out that Ada already has this kind of policy.  In one
reply (<03-01-169@comp.compilers>), it was mentioned that it is a
time-bomb in Ada, since it permits the programmer to write code that
is erroneous but the compiler cannot detect this.  Indeed, the
standard ([1]) says that if an object has been passed via an
unspecified parameter passing mechanism, is written via one access
path and read via another, "possible consequences are that
Program_Error is raised, or the newly assigned value is read, or some
old value of the object is read".

For example, in the simplest case, a procedure can take a readonly
'in' argument "arg1" of type X, and an "in out" argument of the same
type. Then, if it writes in arg2 and after that reads arg1, this might
cause a run-time error or other implementation-defined behavior -- but
only if the procedure is called with two identical arguments.

Of course, the erroneous behavior might occur in a more subtle way,
which is not expected to happen.  I just can't think of any realistic
example where this undefinedness would really hurt.

My concerns here are:

- Is this generally considered a dangerous thing in Ada (or in
  general)?

- Have you encountered a non-trivial real-life case where the
  programmer has shot himself in the foot in the form of
  implementation-defined behavior because of the error mentioned above?
  I'd be interested to hear of any such cases.

- If there are such cases, could it have been prevented by having
  different policy in the language?  Do you think it would've been
  better to force the programmer to specify the parameter passing
  mechanism, for example?

Thanks in advance,

Antti Syk�ri

[1] http://www.adaic.org/standards/95aarm/html/AA-6-2.html#I3062



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
@ 2003-02-09  0:41 ` James S. Rogers
  2003-02-09  2:11   ` Robert A Duff
                     ` (2 more replies)
  2003-02-09  2:01 ` Robert A Duff
                   ` (4 subsequent siblings)
  5 siblings, 3 replies; 18+ messages in thread
From: James S. Rogers @ 2003-02-09  0:41 UTC (permalink / raw)


"Antti Sykari" <jsykari@gamma.hut.fi> wrote in message
news:86isvuzabx.fsf@hoastest1-8c.hoasnet.inet.fi...
> Hello,
>
> I recently asked in comp.compilers advice about implementing a
> parameter passing policy for a rather close-to-machine language.  My
> suggestion for the method of passing 'in' parameters to procedures
> was:  Pass everything as readonly by default, and leave the
> by-reference/by-copy decision to the compiler.
>
> It was pointed out that Ada already has this kind of policy.  In one
> reply (<03-01-169@comp.compilers>), it was mentioned that it is a
> time-bomb in Ada, since it permits the programmer to write code that
> is erroneous but the compiler cannot detect this.  Indeed, the
> standard ([1]) says that if an object has been passed via an
> unspecified parameter passing mechanism, is written via one access
> path and read via another, "possible consequences are that
> Program_Error is raised, or the newly assigned value is read, or some
> old value of the object is read".
>
> For example, in the simplest case, a procedure can take a readonly
> 'in' argument "arg1" of type X, and an "in out" argument of the same
> type. Then, if it writes in arg2 and after that reads arg1, this might
> cause a run-time error or other implementation-defined behavior -- but
> only if the procedure is called with two identical arguments.
>
> Of course, the erroneous behavior might occur in a more subtle way,
> which is not expected to happen.  I just can't think of any realistic
> example where this undefinedness would really hurt.
>
> My concerns here are:
>
> - Is this generally considered a dangerous thing in Ada (or in
>   general)?
>
> - Have you encountered a non-trivial real-life case where the
>   programmer has shot himself in the foot in the form of
>   implementation-defined behavior because of the error mentioned above?
>   I'd be interested to hear of any such cases.
>
> - If there are such cases, could it have been prevented by having
>   different policy in the language?  Do you think it would've been
>   better to force the programmer to specify the parameter passing
>   mechanism, for example?

Not at all.

In Ada an IN parameter is treated as a constant within the subprogram
it is passed to. This eliminates the ability to shoot yourself in the foot
with an IN parameter. An OUT or IN OUT parameter can be passed
by value or by reference. The language provides no rules about this.
The difference between the two in Ada is that an OUT parameter
has no reliable initial value, while an IN OUT parameter does.
In fact compiler writers are quite reasonable about their chosen
passing mechanisms. In general, any value larger than a register
is passed by reference. All other values may be passed by copy
or by reference.

There can be no race condition for either situation in a normal
subprogram, since the called subprogram will execute in the
same task as the calling subprogram.

Calling a task entry may involve passing data. This is a form
of communication between tasks. In Ada this happens as part
of a "rendezvous", where the two tasks synchronize at the point
of communication, again eliminating a race condition.

Calling a protected operation is another option for inter-task
communication. Again, protected operations execute within
the calling task, or its proxy in the case of protected entries.

I have never seen a case where Ada parameter modes have
shot the programmer in the foot. Ada parameter passing modes
are a lot safer to use than the rules found for Java. In Java all
primitive types are passed by value and all objects are passed
by reference. You have no choice. This does cause genuine
problems in program design for Java, particularly when you
want to modify the value of a primitive parameter. Since it is
impossible to pass an object by value you have the ever present
danger of unexpected side effects in Java method calls.

Java does not have a direct equivalent of the Ada rendezvous,
nor does it provide an equivalent of Ada protected operations.
Java produces concurrency with a lot more surprises.

Jim Rogers





^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
  2003-02-09  0:41 ` James S. Rogers
@ 2003-02-09  2:01 ` Robert A Duff
  2003-02-09  2:33   ` Vinzent Hoefler
                     ` (2 more replies)
  2003-02-09  2:08 ` Jeffrey Carter
                   ` (3 subsequent siblings)
  5 siblings, 3 replies; 18+ messages in thread
From: Robert A Duff @ 2003-02-09  2:01 UTC (permalink / raw)


Antti Sykari <jsykari@gamma.hut.fi> writes:

> Hello,
> 
> I recently asked in comp.compilers advice about implementing a
> parameter passing policy for a rather close-to-machine language.

Yes, I saw that thread.

The problem with this Ada rule is that it violates abstraction.
You don't know whose responsibility it is to worry about aliases
-- the caller or callee.

>...My
> suggestion for the method of passing 'in' parameters to procedures
> was:  Pass everything as readonly by default, and leave the
> by-reference/by-copy decision to the compiler.
> 
> It was pointed out that Ada already has this kind of policy.  In one
> reply (<03-01-169@comp.compilers>), it was mentioned that it is a
> time-bomb in Ada, since it permits the programmer to write code that
> is erroneous but the compiler cannot detect this.  Indeed, the
> standard ([1]) says that if an object has been passed via an
> unspecified parameter passing mechanism, is written via one access
> path and read via another, "possible consequences are that
> Program_Error is raised, or the newly assigned value is read, or some
> old value of the object is read".
> 
> For example, in the simplest case, a procedure can take a readonly
> 'in' argument "arg1" of type X, and an "in out" argument of the same
> type. Then, if it writes in arg2 and after that reads arg1, this might
> cause a run-time error or other implementation-defined behavior -- but
> only if the procedure is called with two identical arguments.
> 
> Of course, the erroneous behavior might occur in a more subtle way,
> which is not expected to happen.  I just can't think of any realistic
> example where this undefinedness would really hurt.

How about this example:

We have a record representing fractions of whole numbers:

    type Fraction is
        record
            Numerator: Integer;
            Denominator: Positive;
        end record;

    procedure Reciprocal(Result: out Fraction; X: Fraction);
    -- Sets Result to the reciprocal of X.

    procedure Reciprocal(Result: out Fraction; X: Fraction) is
    begin
        if X.Numerator > 0 then
            Result.Numerator := X.Denominator;
            Result.Denominator := X.Numerator;
        ... etc

It seems reasonable (without seeing the body of Reciprocal) to do:

    Reciprocal(Foo, Foo);

If Fractions are passed by copy (which is probably most efficient, since
they fit in just two registers), then it works fine.  If they're passed
by reference, we get the wrong answer.

Of course Reciprocal could be written to avoid the problem (e.g. write
it as a function instead).  That would be less efficient in the
non-alaised case.  But the Ada RM does not make it clear whose
responsibility this problem is -- the caller or the callee.  In Fortran,
the *call* would be wrong.

> My concerns here are:
> 
> - Is this generally considered a dangerous thing in Ada (or in
>   general)?

I consider it a problem in Ada.  But many other languages are worse in
this regard.

> - Have you encountered a non-trivial real-life case where the
>   programmer has shot himself in the foot in the form of
>   implementation-defined behavior because of the error mentioned above?
>   I'd be interested to hear of any such cases.

I don't know.  I would feel more comfortable if one could *prove* that
such things can't happen.

> - If there are such cases, could it have been prevented by having
>   different policy in the language?

Yes.

>...Do you think it would've been
>   better to force the programmer to specify the parameter passing
>   mechanism, for example?

There are drawbacks to that, too:

    - One normally wants the most efficient mechanism, which depends on
      the sizes of the parameters wrt register size.  But that's machine
      dependent, so the compiler ought to deal with it.

    - You can't (efficiently) pass components of packed records by
      reference.  The Pascal rule in this regard is ugly.  (Similar
      issue: slices of arrays.)

One possible solution is to disallow cases that might be aliased.  But
that would require more information than is available to an Ada compiler
-- it would need to know about global variables referenced by each
procedure, for example.

- Bob



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
  2003-02-09  0:41 ` James S. Rogers
  2003-02-09  2:01 ` Robert A Duff
@ 2003-02-09  2:08 ` Jeffrey Carter
  2003-02-10  0:13 ` Leif Holmgren
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: Jeffrey Carter @ 2003-02-09  2:08 UTC (permalink / raw)


Antti Sykari wrote:
> 
> - Is this generally considered a dangerous thing in Ada (or in
>   general)?

It is dangerous in any language that allows subprograms to change the 
value of its actual parameters to pass the same variable to more than 
one parameter of a subprogram. There is nothing unique about Ada in this 
regard.

> 
> - Have you encountered a non-trivial real-life case where the
>   programmer has shot himself in the foot in the form of
>   implementation-defined behavior because of the error mentioned above?
>   I'd be interested to hear of any such cases.

No.

-- 
Jeff Carter
"Death awaits you all, with nasty, big, pointy teeth!"
Monty Python & the Holy Grail




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-09  0:41 ` James S. Rogers
@ 2003-02-09  2:11   ` Robert A Duff
  2003-02-09  2:25   ` Jeffrey Carter
  2003-02-11  8:39   ` Gautier
  2 siblings, 0 replies; 18+ messages in thread
From: Robert A Duff @ 2003-02-09  2:11 UTC (permalink / raw)


"James S. Rogers" <jimmaureenrogers@worldnet.att.net> writes:

> Not at all.
> 
> In Ada an IN parameter is treated as a constant within the subprogram
> it is passed to. This eliminates the ability to shoot yourself in the foot
> with an IN parameter.

Unless the actual parameter is aliased with some global, or some other
parameter (of mode 'in out' or 'out').

>... An OUT or IN OUT parameter can be passed
> by value or by reference. The language provides no rules about this.
> The difference between the two in Ada is that an OUT parameter
> has no reliable initial value, while an IN OUT parameter does.
> In fact compiler writers are quite reasonable about their chosen
> passing mechanisms. In general, any value larger than a register
> is passed by reference. All other values may be passed by copy
> or by reference.

The rule is that elementary types are passed by copy (including copy-out
in the 'in out' or 'out' case).  Arrays and records leave the compiler a
choice (except in the case of limited types).  And that choice can make
a difference in the behavior of the program, unfortunately.

> There can be no race condition for either situation in a normal
> subprogram, since the called subprogram will execute in the
> same task as the calling subprogram.

The issue arises without any multi-tasking.  But in the multi-task case,
it's even worse: an integer is passed by copy (thus no other task can
meddle with the actual), but a record containing a single integer might
be passed either way.

> Calling a task entry may involve passing data. This is a form
> of communication between tasks. In Ada this happens as part
> of a "rendezvous", where the two tasks synchronize at the point
> of communication, again eliminating a race condition.
> 
> Calling a protected operation is another option for inter-task
> communication. Again, protected operations execute within
> the calling task, or its proxy in the case of protected entries.
> 
> I have never seen a case where Ada parameter modes have
> shot the programmer in the foot.

Would it not be better if we could say, "It is not possible to shoot
oneself in one's foot"?

>...Ada parameter passing modes
> are a lot safer to use than the rules found for Java.

Yes, in Java everything's a pointer, so any procedure can modify any of
its parameters (more or less).  Ada is better in that regard.

>... In Java all
> primitive types are passed by value and all objects are passed
> by reference. You have no choice. This does cause genuine
> problems in program design for Java, particularly when you
> want to modify the value of a primitive parameter. Since it is
> impossible to pass an object by value you have the ever present
> danger of unexpected side effects in Java method calls.
> 
> Java does not have a direct equivalent of the Ada rendezvous,
> nor does it provide an equivalent of Ada protected operations.
> Java produces concurrency with a lot more surprises.
> 
> Jim Rogers

- Bob



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-09  0:41 ` James S. Rogers
  2003-02-09  2:11   ` Robert A Duff
@ 2003-02-09  2:25   ` Jeffrey Carter
  2003-02-11  8:39   ` Gautier
  2 siblings, 0 replies; 18+ messages in thread
From: Jeffrey Carter @ 2003-02-09  2:25 UTC (permalink / raw)


James S. Rogers wrote:
> 
> In Ada an IN parameter is treated as a constant within the subprogram
> it is passed to. This eliminates the ability to shoot yourself in the foot
> with an IN parameter. An OUT or IN OUT parameter can be passed
> by value or by reference. The language provides no rules about this.
> The difference between the two in Ada is that an OUT parameter
> has no reliable initial value, while an IN OUT parameter does.
> In fact compiler writers are quite reasonable about their chosen
> passing mechanisms. In general, any value larger than a register
> is passed by reference. All other values may be passed by copy
> or by reference.

This is not entirely correct. In Ada, all elementary types are passed by 
copy, regardless of the parameter mode. Elementary types are all numeric 
types, all enumeration types, and all access types.

All limited types and all tagged types are passed by reference, 
regardless of the parameter mode.

The parameter passing mechanism for all other types is not defined by 
the language. Most compilers do a good job of choosing a parameter 
passing mechanism for such types.

Finally, the rules for out-mode parameters provide for many cases in 
which a reliable initial value does exist and the parameter effectively 
has mode in out. This includes all record types that have a component 
with a default initial value.

-- 
Jeff Carter
"Death awaits you all, with nasty, big, pointy teeth!"
Monty Python & the Holy Grail




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-09  2:01 ` Robert A Duff
@ 2003-02-09  2:33   ` Vinzent Hoefler
  2003-02-09  6:07   ` Richard Riehle
  2003-02-09  7:13   ` Robert I. Eachus
  2 siblings, 0 replies; 18+ messages in thread
From: Vinzent Hoefler @ 2003-02-09  2:33 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> wrote:

>Antti Sykari <jsykari@gamma.hut.fi> writes:
>
>> - Have you encountered a non-trivial real-life case where the
>>   programmer has shot himself in the foot in the form of
>>   implementation-defined behavior because of the error mentioned above?
>>   I'd be interested to hear of any such cases.

I once did encounter such problem. It wasn't Ada, it was Pascal, so it
had nothing to do with "implementation defined", but if you take a
closer look to it, the problem might be considered as similar.

I changed the parameter mode of a string to "const" because there was
no write access to it. So then it was passed by reference instead of
by value like it did before. The bad thing was, this string was part
of another parameter to this procedure so indeed the string got
changed during the call. An example of badly structured data, I'd say.

>I don't know.  I would feel more comfortable if one could *prove* that
>such things can't happen.

Well, that's what SPARK is for.

>One possible solution is to disallow cases that might be aliased.

Like SPARK does. :)


Vinzent.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-09  2:01 ` Robert A Duff
  2003-02-09  2:33   ` Vinzent Hoefler
@ 2003-02-09  6:07   ` Richard Riehle
  2003-02-09  7:13   ` Robert I. Eachus
  2 siblings, 0 replies; 18+ messages in thread
From: Richard Riehle @ 2003-02-09  6:07 UTC (permalink / raw)


Robert A Duff wrote:

> How about this example:
>
> We have a record representing fractions of whole numbers:
>
>     type Fraction is
>         record
>             Numerator: Integer;
>             Denominator: Positive;
>         end record;
>
>     procedure Reciprocal(Result: out Fraction; X: Fraction);
>     -- Sets Result to the reciprocal of X.
>
>     procedure Reciprocal(Result: out Fraction; X: Fraction) is
>     begin
>         if X.Numerator > 0 then
>             Result.Numerator := X.Denominator;
>             Result.Denominator := X.Numerator;
>         ... etc
>
> It seems reasonable (without seeing the body of Reciprocal) to do:
>
>     Reciprocal(Foo, Foo);

Interesting example.   A little bit of a stretch since it would rarely
occur in practice.  However, it is one reason why I proposed, a few
years ago that we add a mode based on the reserved word constant.
In particular, I would like to be able to use that reserved word
anywhere we normally would be allowed to use access.  Your
example suggests it might be useful under other circumstances
as well.

Richard Riehle




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-09  2:01 ` Robert A Duff
  2003-02-09  2:33   ` Vinzent Hoefler
  2003-02-09  6:07   ` Richard Riehle
@ 2003-02-09  7:13   ` Robert I. Eachus
  2003-02-10  4:40     ` Martin Dowie
  2 siblings, 1 reply; 18+ messages in thread
From: Robert I. Eachus @ 2003-02-09  7:13 UTC (permalink / raw)


Robert A Duff wrote:

> The problem with this Ada rule is that it violates abstraction.
> You don't know whose responsibility it is to worry about aliases
> -- the caller or callee.

The callee.  The abstraction rules in Ada basically mean that the callee 
has to support all possible callers, including those that don't exist 
yet.  In addition, there is the assumption that anything that the user 
of a package needs can be found in the package specification.  (Of 
course, many people including myself are quite willing to use comments 
in the specification to document assumptions made by the body, 
exceptions that may be raised, etc.)

> How about this example:
> 
> We have a record representing fractions of whole numbers:
> 
>     type Fraction is
>         record
>             Numerator: Integer;
>             Denominator: Positive;
>         end record;
> 
>     procedure Reciprocal(Result: out Fraction; X: Fraction);
>     -- Sets Result to the reciprocal of X.
> 
>     procedure Reciprocal(Result: out Fraction; X: Fraction) is
>     begin
>         if X.Numerator > 0 then
>             Result.Numerator := X.Denominator;
>             Result.Denominator := X.Numerator;
>         ... etc
> 
> It seems reasonable (without seeing the body of Reciprocal) to do:
> 
>     Reciprocal(Foo, Foo);
> 
> If Fractions are passed by copy (which is probably most efficient, since
> they fit in just two registers), then it works fine.  If they're passed
> by reference, we get the wrong answer.

...and if you write the body as:

  procedure Reciprocal(Result: out Fraction; X: Fraction) is
      begin
          if X.Numerator > 0 then
              Result := (X.Denominator, X.Numerator);
          ... etc

There is no problem.  (The aggregate must be completely evaluated before 
it can be assigned.) Of course it makes more sense to implement this as 
a function:

  function Reciprocal(X: Fraction) return Fraction is
      begin
          if X.Numerator > 0 then
              return (X.Denominator, X.Numerator);
          ... etc

If the subprogram is inlined, then calls of the form Reciprocal(Foo, 
Foo); or Foo := Reciprocal(Foo); may require more instructions than 
Reciprocal(Foo, Bar) or Bar := Reciprocal(Foo);  But this is not a 
problem, it is exactly what you want--the most efficient code in either 
case.

So in general, the problem of aliasing exists in all high level 
languages, and different language take different approaches to defining 
what happens in the painful, sometimes not even possible to recognize 
even at execution time, cases.  However, in well written Ada there are 
very few cases where the issue is likely to come up.  This is because 
Ada provides lots of ways for a subprogram or body to be written in a 
way that makes its correctness independent of aliasing and parameter 
passing conventions.

But the most important thing to remember is that in Ada the place to 
solve the (potential) problem is in the body of the callee, not in the 
caller or the specification of the callee.  For example, if you have a 
record parameter and must force copy semantics, simply write:

procedure Reciprocal(Result: out Fraction; X: Fraction) is
   Temp := X;
begin...

If the compiler passes X by copy, any decent optimizer will eliminate 
the "second" copy.  If you later change the code as (way) above and 
don't need to force copy semantics, you only have to change the 
body--which you are doing anyway--and not the specification (forcing 
recompiles) or all of the callers.




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
                   ` (2 preceding siblings ...)
  2003-02-09  2:08 ` Jeffrey Carter
@ 2003-02-10  0:13 ` Leif Holmgren
  2003-02-10  9:49 ` Rod Chapman
  2003-02-11  9:14 ` Gautier
  5 siblings, 0 replies; 18+ messages in thread
From: Leif Holmgren @ 2003-02-10  0:13 UTC (permalink / raw)


Antti Sykari wrote:
> 
> Hello,
Hi!

> - Have you encountered a non-trivial real-life case where the
>   programmer has shot himself in the foot in the form of
>   implementation-defined behavior because of the error mentioned
>   above?
Yes.

Not exactly due to aliasing but due to exceptions. Consider the
following:

...

  procedure Calc_Routine(X : in out integer) is
  begin
    X:=X+3;
    ...
    raise Calculation_error;
  end Local;

...

  Z:=6;
  declare
    Calc_Routine(Z);
  exception
    when Calculation_Error =>
      null;
  end;
  -- Try guessing what X is.

Actually this was a bad example, and not what appeared in our code. In
reality the procedure did some things with a file whose file handle was
the input parameter. Then closed it, and finally did some other
processing. The last calculations caused an exception. After this the
calling code crashed since it believed that the file was still open.


> - If there are such cases, could it have been prevented by having
>   different policy in the language?  Do you think it would've been
>   better to force the programmer to specify the parameter passing
>   mechanism, for example?

Yes and no. We had not done our homework properly. The ARM states that
you cannot know how parameters are passed. With this knowledge you wont
do this kind of mistaktes.
The solution of this would however have been easier if we could have
added something like %ref like in the good old vax-fortran days. Now we
had to do a lot of restructuring and searching for similar code
fragments (non found).

/Leif



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-09  7:13   ` Robert I. Eachus
@ 2003-02-10  4:40     ` Martin Dowie
  0 siblings, 0 replies; 18+ messages in thread
From: Martin Dowie @ 2003-02-10  4:40 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> wrote in message 
> >     Reciprocal(Foo, Foo);

I think I'm right in saying that SPARK would catch this.

It would be nice if compilers at least warned of this
(simple) case. I imagine that the work involved in spotting
aliased versions of this problem might be a bit expensive($)
to get compiler implementor to include. :-(



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
                   ` (3 preceding siblings ...)
  2003-02-10  0:13 ` Leif Holmgren
@ 2003-02-10  9:49 ` Rod Chapman
  2003-02-11  9:14 ` Gautier
  5 siblings, 0 replies; 18+ messages in thread
From: Rod Chapman @ 2003-02-10  9:49 UTC (permalink / raw)


Antti Sykari <jsykari@gamma.hut.fi> wrote in message news:<86isvuzabx.fsf@hoastest1-8c.hoasnet.inet.fi>...
> - If there are such cases, could it have been prevented by having
>   different policy in the language?

Yes - use SPARK!

>   Do you think it would've been
>   better to force the programmer to specify the parameter passing
>   mechanism, for example?

How?  Forcing programmers to explicitly use access parameters,
for instance, sounds like a really bad idea.

SPARK is free from parameter passing dependencies.  The language
doesn't specify a mechanism (this would be a big mistake, since
the language wouldn't then be a true subset of Ada...), but rather
simply enforces language rules so that it is impossible to write a program
where the mechanism chosen by a compiler can ever result in differing
dynamic semantics at run-time.  These rules are checked by the Examiner.
All violations are detected statically (in polynomial time) for incomplete
programs (basically meaning the rules are chekcable only using
the specification of called units, not their bodies...very important
for doing analysis when you haven't actually finished
writing the program yet!)
 - Rod, SPARK Team



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-09  0:41 ` James S. Rogers
  2003-02-09  2:11   ` Robert A Duff
  2003-02-09  2:25   ` Jeffrey Carter
@ 2003-02-11  8:39   ` Gautier
  2 siblings, 0 replies; 18+ messages in thread
From: Gautier @ 2003-02-11  8:39 UTC (permalink / raw)


James S. Rogers

> In Ada an IN parameter is treated as a constant within the subprogram
> it is passed to. This eliminates the ability to shoot yourself in the foot
> with an IN parameter.

As Robert metioned, you can: an IN parameter and an IN OUT may
reference the same object. In this situation, ypeee: you believe
that your IN parameter is like a rock-solid, unalterable constant,
but in fact it is being peacefully modified in the procedure itself!

> I have never seen a case where Ada parameter modes have
> shot the programmer in the foot.

I have seen a case of translation (from Modula) where a lot
of procedures were behaving wrong because of the above problem.
Passed-by-copy parameters were translated into "in" parameters,
so their eventual direct modifications were detected at compile-time,
and an explicit copy was added (e.g. procedure P(a:T) is aa:T:= a; ...).
But there were cases with "Q(a,b:T; c:in out T);" and calls like
"Q(a,b,a)". :-) Not a warning from any compiler!
________________________________________________________
Gautier  --  http://www.mysunrise.ch/users/gdm/gsoft.htm

NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
                   ` (4 preceding siblings ...)
  2003-02-10  9:49 ` Rod Chapman
@ 2003-02-11  9:14 ` Gautier
  2003-02-11 13:49   ` Antti Sykari
                     ` (2 more replies)
  5 siblings, 3 replies; 18+ messages in thread
From: Gautier @ 2003-02-11  9:14 UTC (permalink / raw)


Antti:

> My concerns here are:
> 
> - Is this generally considered a dangerous thing in Ada (or in
>   general)?

Not enough!

> - Have you encountered a non-trivial real-life case where the
>   programmer has shot himself in the foot in the form of
>   implementation-defined behavior because of the error mentioned above?
>   I'd be interested to hear of any such cases.

See my other reply. IIRC, the worst were cases where procedure P
calls Q, Q calls R and R modifies an IN parameter because it references
also a [IN] OUT, then even the IN parameter of P is also modified after
the call to Q. Add loops and so on... :-}

> - If there are such cases, could it have been prevented by having
>   different policy in the language?  Do you think it would've been
>   better to force the programmer to specify the parameter passing
>   mechanism, for example?

Yes and no: the explicit passing mechanism has the advantage of being
...explicit, but it is not always optimal according to target system.
The "in,in/out,out" is very readable and catches a lot of errors.
The "in", especially, ensures a fast mode and avoiding an explicit
modification. The security problem happens rarely, but it happens.

I'd suggest that compilers issue a warning when the following
conditions meet:
 - there are parameters of the same type, some IN, some [IN] OUT
 - the compiler decides to pass the IN by reference
 - an IN parameter is referenced after an IN OUT was modified
and also:
 - for a call, when the same variable is passed to an IN
   by reference and an [IN] OUT (it doesn't solve the issue of
   ".all" objects!).
________________________________________________________
Gautier  --  http://www.mysunrise.ch/users/gdm/gsoft.htm

NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-11  9:14 ` Gautier
@ 2003-02-11 13:49   ` Antti Sykari
  2003-02-11 17:18   ` Gautier
  2003-02-12  1:09   ` Richard Riehle
  2 siblings, 0 replies; 18+ messages in thread
From: Antti Sykari @ 2003-02-11 13:49 UTC (permalink / raw)


gautier_niouzes@hotmail.com (Gautier) writes: 
>> - If there are such cases, could it have been prevented by having 
>>   different policy in the language?  Do you think it would've been 
>>   better to force the programmer to specify the parameter passing 
>>   mechanism, for example? 
> 
> Yes and no: the explicit passing mechanism has the advantage of
being 
> ...explicit, but it is not always optimal according to target
system. 
> The "in,in/out,out" is very readable and catches a lot of errors. 
> The "in", especially, ensures a fast mode and avoiding an explicit 
> modification. The security problem happens rarely, but it happens. 
> 
> I'd suggest that compilers issue a warning when the following 
> conditions meet: 
>  - there are parameters of the same type, some IN, some [IN] OUT 
>  - the compiler decides to pass the IN by reference 
>  - an IN parameter is referenced after an IN OUT was modified 
> and also: 
>  - for a call, when the same variable is passed to an IN 
>    by reference and an [IN] OUT (it doesn't solve the issue of 
>    ".all" objects!). 
 
I don't think this is enough.  For example, you can pass a largish
part of a record as an IN OUT parameter (I think you can: I'm not
exactly an Ada expert), and the record itself as IN parameter, and
modify your IN parameter that way.
 
Or you could call any other subprogram which has access to the record,
and modify it that way.  In fact, any subprogram call could change it,
so it's really impossible to know when to warn.  You should be able to
guarantee that an IN OUT object is unchanged (unless don't change it
directly yourself) and that an IN object is unchanged.
 
One (partial) solution would be restricted types, which guarantee that
they are the only means to change the object which they denote.  (As
with C99's restrict-qualified pointers, which are there primarily to
allow optimization and don't change the meaning of a correct program).
However, I'm not sure if you can actually trust the compiler to catch
all errors even in the presence of such types.  In C99, for example,
you can still have two restrict-qualified pointers to the same array
if you promise not to use them to access the same values.

Maybe they would be more useful in a more sophisticated type system
(such as Ada's) - or maybe not. A complicated thing.

-Antti



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-11  9:14 ` Gautier
  2003-02-11 13:49   ` Antti Sykari
@ 2003-02-11 17:18   ` Gautier
  2003-02-11 17:29     ` Vinzent Hoefler
  2003-02-12  1:09   ` Richard Riehle
  2 siblings, 1 reply; 18+ messages in thread
From: Gautier @ 2003-02-11 17:18 UTC (permalink / raw)


gautier_niouzes@hotmail.com (Gautier):

> See my other reply. IIRC, the worst were cases where procedure P
> calls Q, Q calls R and R modifies an IN parameter because it references
> also a [IN] OUT, then even the IN parameter of P is also modified after
> the call to Q. Add loops and so on... :-}

Sorry, I recalled wrong: the IN parameter cannot be passed as
a variable, since it is considered as a constant!
The security problem remains on one level (unless I'm missing
a combination, maybe with a pointed object where the pointer is IN ?)
________________________________________________________
Gautier  --  http://www.mysunrise.ch/users/gdm/gsoft.htm

NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-11 17:18   ` Gautier
@ 2003-02-11 17:29     ` Vinzent Hoefler
  0 siblings, 0 replies; 18+ messages in thread
From: Vinzent Hoefler @ 2003-02-11 17:29 UTC (permalink / raw)


gautier_niouzes@hotmail.com (Gautier) wrote:

>The security problem remains on one level (unless I'm missing
>a combination, maybe with a pointed object where the pointer is IN ?)

That could change the object regardless of any parameter calling
mechanism.


Vinzent.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Ada style of passing 'in' parameters considered dangerous?
  2003-02-11  9:14 ` Gautier
  2003-02-11 13:49   ` Antti Sykari
  2003-02-11 17:18   ` Gautier
@ 2003-02-12  1:09   ` Richard Riehle
  2 siblings, 0 replies; 18+ messages in thread
From: Richard Riehle @ 2003-02-12  1:09 UTC (permalink / raw)


Gautier wrote:

> I'd suggest that compilers issue a warning when the following
> conditions meet:
>  - there are parameters of the same type, some IN, some [IN] OUT
>  - the compiler decides to pass the IN by reference
>  - an IN parameter is referenced after an IN OUT was modified
> and also:
>  - for a call, when the same variable is passed to an IN
>    by reference and an [IN] OUT (it doesn't solve the issue of
>    ".all" objects!).

There is an interesting, but seldom engaged, principle that any method
that modifies an object should do only modification, and any method
that queries an object should do only queries.

This is difficult in Ada because it does not use the distiguished
received model.  Therefore,  we are often forced to use modes
of in out  or have a combination of parameters for in and out
on the same data type.  For limited types, in out is often the
only alternative.   Therefore, the notion of issuing a warning
might serve quite nicely to alert a programmer to a potential
problem.

Richard Riehle




^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2003-02-12  1:09 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
2003-02-09  0:41 ` James S. Rogers
2003-02-09  2:11   ` Robert A Duff
2003-02-09  2:25   ` Jeffrey Carter
2003-02-11  8:39   ` Gautier
2003-02-09  2:01 ` Robert A Duff
2003-02-09  2:33   ` Vinzent Hoefler
2003-02-09  6:07   ` Richard Riehle
2003-02-09  7:13   ` Robert I. Eachus
2003-02-10  4:40     ` Martin Dowie
2003-02-09  2:08 ` Jeffrey Carter
2003-02-10  0:13 ` Leif Holmgren
2003-02-10  9:49 ` Rod Chapman
2003-02-11  9:14 ` Gautier
2003-02-11 13:49   ` Antti Sykari
2003-02-11 17:18   ` Gautier
2003-02-11 17:29     ` Vinzent Hoefler
2003-02-12  1:09   ` Richard Riehle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox