comp.lang.ada
 help / color / mirror / Atom feed
* How to get nice with GNAT?
@ 2014-11-21 11:41 Natasha Kerensikova
  2014-11-21 12:42 ` Björn Lundin
                   ` (7 more replies)
  0 siblings, 8 replies; 59+ messages in thread
From: Natasha Kerensikova @ 2014-11-21 11:41 UTC (permalink / raw)


Hello,

I happen to have found a situation in which symbolic traceback is a
great help, but I have been a bit surprise by the (lack of) support in
the platform to which I have access.

I have been using GNAT.Traceback.Symbolic.Symbolic_Traceback, is there a
more portable way?

In FreeBSD, with GNAT 4.9.0, I get an output like the following, with
the first line actually repeated about a hundred times:
> BFD: Dwarf Error: found dwarf version '4', this reader only handles version 2 information.
> 0x7e7773 in asis.gela.contexts.open at ??:0
> 0x78cb43 in asis.ada_environments.open at ??:0
> 0x46a7da in adactl at ??:0
> 0x40690e in main at ??:0
> 0x4069df in <_start> at ??:0
> 0x800da3ffe in ?? at ??:0

In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
what I consider as perfect:
> 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
> 0x481a57 in adactl at adactl.adb:90
> 0x417029 in main at b~adactl.adb:817
> 0x8015a4347 in ?? at ??:0
> 0x41706e in <_start> at ??:0

In Fedora 20, with GNAT 4.8.3, it looks like the following, which I find
the worst:
> 0x000000000069307D
> 0x00000000004733BD
> 0x0000000000410824
> 0x0000003CC5A21D63
> 0x000000000041086F
> 0xFFFFFFFFFFFFFFFE

Considering the versions, I doubt that's the cause for the discrepancy.
I would rather wager on something related to addr2line.

As a user, is there something I can do to improve the traceback
representation on those platforms?
Or is it completely in the hands of the GNAT packager/maintainer?


Thanks in advance for your help,
Natasha


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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
@ 2014-11-21 12:42 ` Björn Lundin
  2014-11-21 22:55 ` Randy Brukardt
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 59+ messages in thread
From: Björn Lundin @ 2014-11-21 12:42 UTC (permalink / raw)


On 2014-11-21 12:41, Natasha Kerensikova wrote:


> As a user, is there something I can do to improve the traceback
> representation on those platforms?
> Or is it completely in the hands of the GNAT packager/maintainer?
>

I run gnat on Aix/win32/linux32/64
and until recently, I tucked everything related
to stacktrace into a package Stacktrace.


package Stacktrace is
  procedure Tracebackinfo(E : Ada.Exceptions.Exception_Occurrence) ;
end Stacktrace;

used as

procedure bla is
...
...
exception
  when E: others =>
  Stacktrace.Tracebackinfo(E);
end ;

where i called
Ada.Exceptions.Exception_Name(E);
Ada.Exceptions.Exception_Message(E);
Ada.Exceptions.Exception_Information(E);

and output them

however, from Gnat GPL 2014 (64) and gnat fsf on debian Jessie
 (gnat 4.9 i think) the Tracebackinfo is not called anymore.

So my current workaround is to print those function directly
like

procedure bla is
...

exception
  when E: others =>
    declare
      Last_Exception_Name     : constant String  :=
Ada.Exceptions.Exception_Name(E);
      Last_Exception_Messsage : constant String  :=
Ada.Exceptions.Exception_Message(E);
      Last_Exception_Info     : constant String  :=
Ada.Exceptions.Exception_Information(E);
    begin
      Log(Last_Exception_Name);
      Log("Message : " & Last_Exception_Messsage);
      Log(Last_Exception_Info);
      Log("addr2line" & " --functions --basenames --exe=" &
           Ada.Command_Line.Command_Name & " " &
Stacktrace.Pure_Hexdump(Last_Exception_Info));
    end ;

end bla;



the function Pure_Hexdump strips away
everything before the first 0x in the string.


final output is like

2014-11-21 13:33:26.278 SQL.NOT_CONNECTED
2014-11-21 13:33:26.278 Message : Sql.Connect: Not_Connected
2014-11-21 13:33:26.278 Exception name: SQL.NOT_CONNECTED
Message: Sql.Connect: Not_Connected
Call stack traceback locations:
0x5be389 0x5cd93c 0x40c988 0x7fca95a8beab 0x40bab7

2014-11-21 13:33:26.278 addr2line --functions --basenames
--exe=/home/bnl/bnlbot/botstart/bot-1-0/target/bin/back_hitrate 0x5be389
0x5cd93c 0x40c988 0x7fca95a8beab 0x40bab7

and running addr2line gives

 addr2line --functions --basenames
--exe=/home/bnl/bnlbot/botstart/bot-1-0/target/bin/back_hitrate 0x5be389
0x5cd93c 0x40c988 0x7fca95a8beab 0x40bab7
sql__connect
sql.adb:432
_ada_back_hitrate
back_hitrate.adb:165
main
b~back_hitrate.adb:761
??
??:0
_start
??:?


A bit clumpsy but good enough for my _hobby_ projects.

--
Björn

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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
  2014-11-21 12:42 ` Björn Lundin
@ 2014-11-21 22:55 ` Randy Brukardt
  2014-11-21 23:13   ` Björn Lundin
  2014-11-22  9:45   ` How to get nice traceback " Natasha Kerensikova
  2014-11-22 10:11 ` How to get nice " gautier_niouzes
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 59+ messages in thread
From: Randy Brukardt @ 2014-11-21 22:55 UTC (permalink / raw)


"Natasha Kerensikova" <lithiumcat@instinctive.eu> wrote in message 
news:slrnm6u97f.nrc.lithiumcat@nat.rebma.instinctive.eu...
> Hello,
>
> I happen to have found a situation in which symbolic traceback is a
> great help, but I have been a bit surprise by the (lack of) support in
> the platform to which I have access.

There is no standard for traceback, you are totally at the mercy of your 
compiler vendor.

>In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
>what I consider as perfect:
>> 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
>> 0x481a57 in adactl at adactl.adb:90
>> 0x417029 in main at b~adactl.adb:817
>> 0x8015a4347 in ?? at ??:0
>> 0x41706e in <_start> at ??:0

No, perfect is:
** Unhandled CONSTRAINT_ERROR
   Index or Subtype out of bounds - Pos of Error Value = -1
On Line Number 484 In J2TYPE_PROFILE_CHECKING.END_SPEC_AND_DO_DELAYED_THUNKS
Called from line number 1914 In J2SEMANTIC_ROUTINES.SEMANTICS
Called from line number 466 In JANUS2.SEMDRIVER
Called from line number 527 In JANUS2

:-) :-)

But you'd need to get Janus/Ada to get that. (Maybe it would need mixed case 
for the subprogram names to be even more perfect.) [It's even more perfect 
if the exception is re-raised, because it saves and displays part of both 
traces, the one of the original exception and of the place it was last 
re-raised.]

The best you can do portably is with Exception_Message and Exception_Name; 
the contents of Exception_Information is implementer-defined (the above is 
what you'd get for Janus/Ada, but most compilers don't try that hard).

And be glad that you get anything. Most of the compilers I've worked with 
give you nothing useful at all. (The only error message from the first C 
compiler I worked with was "Bus error - core dumped". Up to you to figure 
out anything else.)


                                                  Randy.





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

* Re: How to get nice with GNAT?
  2014-11-21 22:55 ` Randy Brukardt
@ 2014-11-21 23:13   ` Björn Lundin
  2014-11-22  9:45   ` How to get nice traceback " Natasha Kerensikova
  1 sibling, 0 replies; 59+ messages in thread
From: Björn Lundin @ 2014-11-21 23:13 UTC (permalink / raw)


On 2014-11-21 23:55, Randy Brukardt wrote:
> And be glad that you get anything. Most of the compilers I've worked with 
> give you nothing useful at all. (The only error message from the first C 
> compiler I worked with was "Bus error - core dumped". Up to you to figure 
> out anything else.)

Alsys Ada on Aix, or was it Verdix ?
Anyway one of them said

'Main program abandoned'

and that was it.

Just as helpful...

--
Björn

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

* Re: How to get nice traceback with GNAT?
  2014-11-21 22:55 ` Randy Brukardt
  2014-11-21 23:13   ` Björn Lundin
@ 2014-11-22  9:45   ` Natasha Kerensikova
  2014-11-22  9:57     ` Dmitry A. Kazakov
  2014-11-24 22:35     ` Randy Brukardt
  1 sibling, 2 replies; 59+ messages in thread
From: Natasha Kerensikova @ 2014-11-22  9:45 UTC (permalink / raw)


On 2014-11-21, Randy Brukardt <randy@rrsoftware.com> wrote:
> "Natasha Kerensikova" <lithiumcat@instinctive.eu> wrote in message 
> news:slrnm6u97f.nrc.lithiumcat@nat.rebma.instinctive.eu...
>> Hello,
>>
>> I happen to have found a situation in which symbolic traceback is a
>> great help, but I have been a bit surprise by the (lack of) support in
>> the platform to which I have access.
>
> There is no standard for traceback, you are totally at the mercy of your 
> compiler vendor.

Indeed I am, but I don't think portability in debugging is that
important: I only need a set of tools that work on the platform where
debugging is performed. So when dealing with portable/fundamental bugs,
I'm free to choose the platform where the best tools for that task are
available.

>>In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
>>what I consider as perfect:
>>> 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
>>> 0x481a57 in adactl at adactl.adb:90
>>> 0x417029 in main at b~adactl.adb:817
>>> 0x8015a4347 in ?? at ??:0
>>> 0x41706e in <_start> at ??:0
>
> No, perfect is:
> ** Unhandled CONSTRAINT_ERROR
>    Index or Subtype out of bounds - Pos of Error Value = -1
> On Line Number 484 In J2TYPE_PROFILE_CHECKING.END_SPEC_AND_DO_DELAYED_THUNKS
> Called from line number 1914 In J2SEMANTIC_ROUTINES.SEMANTICS
> Called from line number 466 In JANUS2.SEMDRIVER
> Called from line number 527 In JANUS2

It might be nitpicking, but as far as the traceback (word I
unfortunately missed in the subject) you actually provide less
information: GNAT has function name, file name, line number, while yours
lacks the file name (might be easy to find out, but that's still a
mental overhead nonetheless).

As far as the exception message goes, I agree that yours is quite
impressive. I didn't mention it in the OP because I'm actually chasing
user exceptions (explicit raise statements), so I have the power to
improve the exception message. Compare to the traceback, which is to
tied to the compiler internals that a mere user has no power to improve
anything. I can't even guess what is going in GNAT to get so wildly
different outputs on different platforms.



Natasha


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

* Re: How to get nice traceback with GNAT?
  2014-11-22  9:45   ` How to get nice traceback " Natasha Kerensikova
@ 2014-11-22  9:57     ` Dmitry A. Kazakov
  2014-11-24 22:35     ` Randy Brukardt
  1 sibling, 0 replies; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-22  9:57 UTC (permalink / raw)


On Sat, 22 Nov 2014 09:45:16 +0000 (UTC), Natasha Kerensikova wrote:

> I didn't mention it in the OP because I'm actually chasing
> user exceptions (explicit raise statements),

You might find GNAT.Exception_Traces very useful for the purpose.

> so I have the power to
> improve the exception message. Compare to the traceback, which is to
> tied to the compiler internals that a mere user has no power to improve
> anything. I can't even guess what is going in GNAT to get so wildly
> different outputs on different platforms.

It depends on whether the vendor tries to use OS services and the formats
of the executable and the stack frames. If you are less dependent on the OS
as Janus, I guess is, it is easier to do, but also you will have problems
with non-Ada components. What about an exception raised in a callback
procedure called from a C-library? Otherwise, it is a quite complicated
thing aggravated under Windows by MS vs. MinGW issues.

From my experience of chasing exceptions, the only right solution would be
exception contracts.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
  2014-11-21 12:42 ` Björn Lundin
  2014-11-21 22:55 ` Randy Brukardt
@ 2014-11-22 10:11 ` gautier_niouzes
  2014-11-22 10:40   ` Natasha Kerensikova
  2014-11-22 22:44 ` brbarkstrom
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 59+ messages in thread
From: gautier_niouzes @ 2014-11-22 10:11 UTC (permalink / raw)


Below, a generic solution, unchanged since around year 2000.
This way you can have a pure Ada program but a decent GNAT trace-back.
Why AdaCore never made it just to include these few Put_Line in their run-time is a bit a mystery.
_________________________ 
Gautier's Ada programming 
http://sf.net/users/gdemont

------------------------------------------------------------------------------
--  File:            TB_Wrap.ads
--  Description:     Trace-back wrapper for GNAT 3.13p+ (spec.)
------------------------------------------------------------------------------

generic

  with procedure My_main_procedure;

procedure TB_Wrap;


------------------------------------------------------------------------------
--  File:            TB_Wrap.adb
--  Description:     Trace-back wrapper for GNAT 3.13p+ (body)
------------------------------------------------------------------------------

with GNAT.Traceback.Symbolic, Ada.Exceptions, Ada.Text_IO;
use Ada.Text_IO;

procedure TB_Wrap is
  --  pragma Compiler_options("-g");
  --  pragma Binder_options("-E");
begin
  My_main_procedure;
exception
  when E: others =>
    New_Line;
    Put_Line("--------------------[ Unhandled exception ]-----------------");
    Put_Line(" > Name of exception . . . . .: " &
             Ada.Exceptions.Exception_Name(E) );
    Put_Line(" > Message for exception . . .: " &
             Ada.Exceptions.Exception_Message(E) );
    Put_Line(" > Trace-back of call stack: " );
    Put_Line( GNAT.Traceback.Symbolic.Symbolic_Traceback(E) );
end TB_Wrap;

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

* Re: How to get nice with GNAT?
  2014-11-22 10:11 ` How to get nice " gautier_niouzes
@ 2014-11-22 10:40   ` Natasha Kerensikova
  0 siblings, 0 replies; 59+ messages in thread
From: Natasha Kerensikova @ 2014-11-22 10:40 UTC (permalink / raw)


On 2014-11-22, gautier_niouzes@hotmail.com <gautier_niouzes@hotmail.com> wrote:
> Below, a generic solution, unchanged since around year 2000.
> This way you can have a pure Ada program but a decent GNAT trace-back.
> Why AdaCore never made it just to include these few Put_Line in their run-time is a bit a mystery.

The whole post is about the output of:

>     Put_Line(" > Trace-back of call stack: " );
>     Put_Line( GNAT.Traceback.Symbolic.Symbolic_Traceback(E) );

The quotes in the OP shows verying levels of informations, from almost
useless to perfectly complete.
And the question is, how do I make GNAT output the useful version on the
platforms where by default it doesn't?


Natasha


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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
                   ` (2 preceding siblings ...)
  2014-11-22 10:11 ` How to get nice " gautier_niouzes
@ 2014-11-22 22:44 ` brbarkstrom
  2014-11-22 23:24   ` Jeffrey Carter
  2014-11-23 18:06   ` Björn Lundin
  2014-11-23 16:13 ` brbarkstrom
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-22 22:44 UTC (permalink / raw)


On Friday, November 21, 2014 6:41:45 AM UTC-5, Natasha Kerensikova wrote:
> Hello,
> 
> I happen to have found a situation in which symbolic traceback is a
> great help, but I have been a bit surprise by the (lack of) support in
> the platform to which I have access.
> 
> I have been using GNAT.Traceback.Symbolic.Symbolic_Traceback, is there a
> more portable way?
> 
> In FreeBSD, with GNAT 4.9.0, I get an output like the following, with
> the first line actually repeated about a hundred times:
> > BFD: Dwarf Error: found dwarf version '4', this reader only handles version 2 information.
> > 0x7e7773 in asis.gela.contexts.open at ??:0
> > 0x78cb43 in asis.ada_environments.open at ??:0
> > 0x46a7da in adactl at ??:0
> > 0x40690e in main at ??:0
> > 0x4069df in <_start> at ??:0
> > 0x800da3ffe in ?? at ??:0
> 
> In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
> what I consider as perfect:
> > 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
> > 0x481a57 in adactl at adactl.adb:90
> > 0x417029 in main at b~adactl.adb:817
> > 0x8015a4347 in ?? at ??:0
> > 0x41706e in <_start> at ??:0
> 
> In Fedora 20, with GNAT 4.8.3, it looks like the following, which I find
> the worst:
> > 0x000000000069307D
> > 0x00000000004733BD
> > 0x0000000000410824
> > 0x0000003CC5A21D63
> > 0x000000000041086F
> > 0xFFFFFFFFFFFFFFFE
> 
> Considering the versions, I doubt that's the cause for the discrepancy.
> I would rather wager on something related to addr2line.
> 
> As a user, is there something I can do to improve the traceback
> representation on those platforms?
> Or is it completely in the hands of the GNAT packager/maintainer?
> 
> 
> Thanks in advance for your help,
> Natasha

One possibility is to get in the habit of putting exception handling
messages in every procedure interface, as in

procedure DoSomething(stuff;
                      OK      :    out Boolean;
                      Err_Msg :    out Bounded_String);

if DoSomething throws an exception, the calling program can detect
that OK is false and receive a message identifying the cause.
Since the Ada Bounded_Strings package (see the RM) can append strings,
you can return useful diagnostics by stringing together messages like

Err_Msg := Vstring.To_Bounded_String("Error in DoSomething");
Err_Msg := Vstring.Append(Err_Msg, " caused by bad stuff ");
...

I don't know how much overhead this will cause, but if you're working
with complex logic, this approach can help identify where the problem
is occurring.  One advantage is that you can tailor the format and
content of the messages so that you can understand what happened.
With some thought, you could even label the messages and put them
into a catalog for documenting errors on a production version.

Bruce B.


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

* Re: How to get nice with GNAT?
  2014-11-22 22:44 ` brbarkstrom
@ 2014-11-22 23:24   ` Jeffrey Carter
  2014-11-23 18:06   ` Björn Lundin
  1 sibling, 0 replies; 59+ messages in thread
From: Jeffrey Carter @ 2014-11-22 23:24 UTC (permalink / raw)


On 11/22/2014 03:44 PM, brbarkstrom@gmail.com wrote:
> 
> One possibility is to get in the habit of putting exception handling
> messages in every procedure interface, as in
> 
> procedure DoSomething(stuff;
>                       OK      :    out Boolean;
>                       Err_Msg :    out Bounded_String);
> 
> if DoSomething throws an exception, the calling program can detect
> that OK is false and receive a message identifying the cause.

This is terrible advice. Boolean is a by-copy type; if the procedure call raises
an exception, then no value will have been copied out to the actual parameter.
Bounded_String may also be passed by copy.

This only works if you never raise exceptions, in which case you might as well
use a primitive language without exceptions.

-- 
Jeff Carter
"C++ is vast and dangerous, a sort of Mordor of
programming languages."
Jason R. Fruit
120


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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
                   ` (3 preceding siblings ...)
  2014-11-22 22:44 ` brbarkstrom
@ 2014-11-23 16:13 ` brbarkstrom
  2014-11-23 16:18   ` J-P. Rosen
  2014-11-23 17:02   ` Jeffrey Carter
  2014-11-23 17:41 ` brbarkstrom
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-23 16:13 UTC (permalink / raw)


On Friday, November 21, 2014 6:41:45 AM UTC-5, Natasha Kerensikova wrote:
> Hello,
> 
> I happen to have found a situation in which symbolic traceback is a
> great help, but I have been a bit surprise by the (lack of) support in
> the platform to which I have access.
> 
> I have been using GNAT.Traceback.Symbolic.Symbolic_Traceback, is there a
> more portable way?
> 
> In FreeBSD, with GNAT 4.9.0, I get an output like the following, with
> the first line actually repeated about a hundred times:
> > BFD: Dwarf Error: found dwarf version '4', this reader only handles version 2 information.
> > 0x7e7773 in asis.gela.contexts.open at ??:0
> > 0x78cb43 in asis.ada_environments.open at ??:0
> > 0x46a7da in adactl at ??:0
> > 0x40690e in main at ??:0
> > 0x4069df in <_start> at ??:0
> > 0x800da3ffe in ?? at ??:0
> 
> In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
> what I consider as perfect:
> > 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
> > 0x481a57 in adactl at adactl.adb:90
> > 0x417029 in main at b~adactl.adb:817
> > 0x8015a4347 in ?? at ??:0
> > 0x41706e in <_start> at ??:0
> 
> In Fedora 20, with GNAT 4.8.3, it looks like the following, which I find
> the worst:
> > 0x000000000069307D
> > 0x00000000004733BD
> > 0x0000000000410824
> > 0x0000003CC5A21D63
> > 0x000000000041086F
> > 0xFFFFFFFFFFFFFFFE
> 
> Considering the versions, I doubt that's the cause for the discrepancy.
> I would rather wager on something related to addr2line.
> 
> As a user, is there something I can do to improve the traceback
> representation on those platforms?
> Or is it completely in the hands of the GNAT packager/maintainer?
> 
> 
> Thanks in advance for your help,
> Natasha

That is not correct.  I routinely set OK := False; at the beginning
of the procedure and only set it to True when the procedure has completed
correctly.  The output from the procedure does provide the last value
of OK before the procedure raises the exception -- if the procedure doesn't
handle the exception.

You can set outgoing parameters in the code
after raising the exception.  In other words, the code for a procedure
looks like

procedure This_Procedure(OK      :    out Boolean;
                         Err_Msg :    out Bounded_String);
is
   ...
   This_Kind_Of_Exception : exception;
   ...
begin
   ...
   if (Bad_Condition = True) then
      raise This_Kind_Of_Exception;
   end if;
   ...
exception 
   when ...
   ...
   when This_Kind_Of_Exception =>
      Err_Msg := Vstring.To_Bounded_String("This procedure encountered
                                            a Bad_Condition : ");
      Err_Msg := Vstring.Append(Err_Msg, ...);
   ...
end This_Procedure;

The code that calls This_Procedure can choose how it wants to handle
the exception.  For example, 

...
    This_Procedure(OK      => OK,
                   Err_Msg => Err_Msg);
    if not OK then
       Put_Line(Vstring.To_String(Err_Msg));
       -- Take other exception handling steps
    end if;
...

will print out the error message.  I'll grant the programmer may have
to handle complex chains of exception handling.  However, it does work
and can provide the thread of exceptions for understanding what happened.

Also, this is one strategy for dealing with exceptions in Web interfaces,
where it's important to avoid a fatal error that shuts down a working
program that's interacting with users.

I use this approach routinely.  It is a big help during debugging.  If
the exception handling is left in, it can also catch problems when the
debugging has moved along and you've forgotten about it.  That saves
time.

Bruce B.

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

* Re: How to get nice with GNAT?
  2014-11-23 16:13 ` brbarkstrom
@ 2014-11-23 16:18   ` J-P. Rosen
  2014-11-23 17:02   ` Jeffrey Carter
  1 sibling, 0 replies; 59+ messages in thread
From: J-P. Rosen @ 2014-11-23 16:18 UTC (permalink / raw)


Le 23/11/2014 17:13, brbarkstrom@gmail.com a écrit :
> That is not correct.  I routinely set OK := False; at the beginning
> of the procedure and only set it to True when the procedure has completed
> correctly.  The output from the procedure does provide the last value
> of OK before the procedure raises the exception -- if the procedure doesn't
> handle the exception.
RM 6.4.1(17). The language does not specify what happens to out
parameters passed by copy in the case of an exception. It may work in
some implementations, but it's not portable

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

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

* Re: How to get nice with GNAT?
  2014-11-23 16:13 ` brbarkstrom
  2014-11-23 16:18   ` J-P. Rosen
@ 2014-11-23 17:02   ` Jeffrey Carter
  1 sibling, 0 replies; 59+ messages in thread
From: Jeffrey Carter @ 2014-11-23 17:02 UTC (permalink / raw)


On 11/23/2014 09:13 AM, brbarkstrom@gmail.com wrote:
> 
> That is not correct.  I routinely set OK := False; at the beginning
> of the procedure and only set it to True when the procedure has completed
> correctly.  The output from the procedure does provide the last value
> of OK before the procedure raises the exception -- if the procedure doesn't
> handle the exception.

This is compiler-dependent behavior. Your code is not portable.

>    if (Bad_Condition = True) then

if Bad_Condition then

Comparing Boolean variables to Boolean literals usually indicates someone who
doesn't understand Booleans.

> The code that calls This_Procedure can choose how it wants to handle
> the exception.  For example, 
> 
> ...
>     This_Procedure(OK      => OK,
>                    Err_Msg => Err_Msg);
>     if not OK then
>        Put_Line(Vstring.To_String(Err_Msg));
>        -- Take other exception handling steps
>     end if;

If the call to This_Procedure raises an exception, execution will not get to the
if statement.

> ...
> 
> will print out the error message.  I'll grant the programmer may have
> to handle complex chains of exception handling.  However, it does work
> and can provide the thread of exceptions for understanding what happened.
> 
> Also, this is one strategy for dealing with exceptions in Web interfaces,
> where it's important to avoid a fatal error that shuts down a working
> program that's interacting with users.
> 
> I use this approach routinely.  It is a big help during debugging.  If
> the exception handling is left in, it can also catch problems when the
> debugging has moved along and you've forgotten about it.  That saves
> time.
> 
> Bruce B.
> 


-- 
Jeff Carter
"This school was here before you came,
and it'll be here before you go."
Horse Feathers
48


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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
                   ` (4 preceding siblings ...)
  2014-11-23 16:13 ` brbarkstrom
@ 2014-11-23 17:41 ` brbarkstrom
  2014-11-23 19:22   ` Simon Wright
  2014-11-23 20:49   ` Jeffrey Carter
  2014-11-23 18:55 ` brbarkstrom
  2014-11-23 19:30 ` brbarkstrom
  7 siblings, 2 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-23 17:41 UTC (permalink / raw)


On Friday, November 21, 2014 6:41:45 AM UTC-5, Natasha Kerensikova wrote:
> Hello,
> 
> I happen to have found a situation in which symbolic traceback is a
> great help, but I have been a bit surprise by the (lack of) support in
> the platform to which I have access.
> 
> I have been using GNAT.Traceback.Symbolic.Symbolic_Traceback, is there a
> more portable way?
> 
> In FreeBSD, with GNAT 4.9.0, I get an output like the following, with
> the first line actually repeated about a hundred times:
> > BFD: Dwarf Error: found dwarf version '4', this reader only handles version 2 information.
> > 0x7e7773 in asis.gela.contexts.open at ??:0
> > 0x78cb43 in asis.ada_environments.open at ??:0
> > 0x46a7da in adactl at ??:0
> > 0x40690e in main at ??:0
> > 0x4069df in <_start> at ??:0
> > 0x800da3ffe in ?? at ??:0
> 
> In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
> what I consider as perfect:
> > 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
> > 0x481a57 in adactl at adactl.adb:90
> > 0x417029 in main at b~adactl.adb:817
> > 0x8015a4347 in ?? at ??:0
> > 0x41706e in <_start> at ??:0
> 
> In Fedora 20, with GNAT 4.8.3, it looks like the following, which I find
> the worst:
> > 0x000000000069307D
> > 0x00000000004733BD
> > 0x0000000000410824
> > 0x0000003CC5A21D63
> > 0x000000000041086F
> > 0xFFFFFFFFFFFFFFFE
> 
> Considering the versions, I doubt that's the cause for the discrepancy.
> I would rather wager on something related to addr2line.
> 
> As a user, is there something I can do to improve the traceback
> representation on those platforms?
> Or is it completely in the hands of the GNAT packager/maintainer?
> 
> 
> Thanks in advance for your help,
> Natasha

I'm working in GNAT GPL, so my suggestion may not work with every
compiler.

On the other hand, in my code, the if following the exception in the
procedure is picked up and executed properly.  The code doesn't act
like the program has to fail if any exception is raised.

It may be that the sensible approach is to try this solution on the
compiler you have at hand.  If it doesn't work, you'll need to do something
else.  If it does, I think it can be helpful in diagnosing problems,
particularly if you have conditions where the system exceptions (like
those in the IO_Exceptions package) are not the only ones a particular 
algorithm might raise.

I'm often doing debugging on sequential algorithms.  However, sending out
a Bounded_String to print may not work well in a concurrent environment.
An approach that may be useful (at least for GNAT) would be to assign
a numerical code value to the error message.  In that case, a procedure
might act like a C subroutine that returns a numerical value of 0 if 
there were no exceptions or some other value if there was one.

With some careful system design, it would be possible to arrange for an 
exception classification.  Thus, some exceptions could be classified as fatal 
and lead to shutdown.  Other exceptions could be classified as "nuisances" 
and logged.  The difficulty in dealing with error classification early in 
the design process is that the design is malleable.  Thus, one could either 
spend a fair amount of development time pinning down the structure of the 
exceptions or do the formalization after there's some experience.

Some kinds of exceptions, such as equipment failures, may be difficult to
handle regardless.  If the CPU that's executing the procedural code fails
in the middle of the procedure (because of a power outage caused by a a failure
of the UPS), it's obvious that there won't be an exception handling message
coming out of the procedure.  However, algorithmic exceptions don't necessarily
have that kind of critical character.

Bruce B.

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

* Re: How to get nice with GNAT?
  2014-11-22 22:44 ` brbarkstrom
  2014-11-22 23:24   ` Jeffrey Carter
@ 2014-11-23 18:06   ` Björn Lundin
  1 sibling, 0 replies; 59+ messages in thread
From: Björn Lundin @ 2014-11-23 18:06 UTC (permalink / raw)


On 2014-11-22 23:44, brbarkstrom@gmail.com wrote:

> 
> One possibility is to get in the habit of putting exception handling
> messages in every procedure interface, as in
> 
> procedure DoSomething(stuff;
>                       OK      :    out Boolean;
>                       Err_Msg :    out Bounded_String);
> 
> if DoSomething throws an exception, the calling program can detect
> that OK is false and receive a message identifying the cause.

To me, it sounds like c-programming.
Check the result after each call, because of the
lack of exceptions.

But this is Ada where exceptions should be
dealt with as is. Much easier to read,
better program flow.

And the OP did not want to get rid of exceptions,
just get reasonable crash-dumps.


--
Björn


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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
                   ` (5 preceding siblings ...)
  2014-11-23 17:41 ` brbarkstrom
@ 2014-11-23 18:55 ` brbarkstrom
  2014-11-23 19:30 ` brbarkstrom
  7 siblings, 0 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-23 18:55 UTC (permalink / raw)


On Friday, November 21, 2014 6:41:45 AM UTC-5, Natasha Kerensikova wrote:
> Hello,
> 
> I happen to have found a situation in which symbolic traceback is a
> great help, but I have been a bit surprise by the (lack of) support in
> the platform to which I have access.
> 
> I have been using GNAT.Traceback.Symbolic.Symbolic_Traceback, is there a
> more portable way?
> 
> In FreeBSD, with GNAT 4.9.0, I get an output like the following, with
> the first line actually repeated about a hundred times:
> > BFD: Dwarf Error: found dwarf version '4', this reader only handles version 2 information.
> > 0x7e7773 in asis.gela.contexts.open at ??:0
> > 0x78cb43 in asis.ada_environments.open at ??:0
> > 0x46a7da in adactl at ??:0
> > 0x40690e in main at ??:0
> > 0x4069df in <_start> at ??:0
> > 0x800da3ffe in ?? at ??:0
> 
> In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
> what I consider as perfect:
> > 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
> > 0x481a57 in adactl at adactl.adb:90
> > 0x417029 in main at b~adactl.adb:817
> > 0x8015a4347 in ?? at ??:0
> > 0x41706e in <_start> at ??:0
> 
> In Fedora 20, with GNAT 4.8.3, it looks like the following, which I find
> the worst:
> > 0x000000000069307D
> > 0x00000000004733BD
> > 0x0000000000410824
> > 0x0000003CC5A21D63
> > 0x000000000041086F
> > 0xFFFFFFFFFFFFFFFE
> 
> Considering the versions, I doubt that's the cause for the discrepancy.
> I would rather wager on something related to addr2line.
> 
> As a user, is there something I can do to improve the traceback
> representation on those platforms?
> Or is it completely in the hands of the GNAT packager/maintainer?
> 
> 
> Thanks in advance for your help,
> Natasha

Maybe another way of putting my suggestion is trying to avoid crash dumps
if the exception handling allows a more nuanced approach.  I haven't seen
much discussion in the Ada literature about the structure of error tracking,
although a systematic discussion might help reduce the cost of maintenance.

I didn't like the C function value returns because a numerical value doesn't
give much of a clue about what happened.  With the approach I've suggested,
the cause of the problem can be understood without a crash dump (most of the
time).  For example, if the problem is a bad numerical value being passed
in, the error message can include the value, as well as its name.  Knowing
that the input was the problem makes it easier to feel somewhat more confident
about the logic of the procedure.

Anyway, I'm just trying to make things easier for practical programmers.
If this shoe doesn't fit, you aren't required to wear it.

Bruce B.

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

* Re: How to get nice with GNAT?
  2014-11-23 17:41 ` brbarkstrom
@ 2014-11-23 19:22   ` Simon Wright
  2014-11-23 20:49   ` Jeffrey Carter
  1 sibling, 0 replies; 59+ messages in thread
From: Simon Wright @ 2014-11-23 19:22 UTC (permalink / raw)


brbarkstrom@gmail.com writes:

> However, sending out a Bounded_String to print may not work well in a
> concurrent environment.

My last project was capable of sending out many (unbounded) strings per
second to output via a protected queue and a printing task. On the
desktop the output went to the screen, on the target to a system-wide
logger.

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

* Re: How to get nice with GNAT?
  2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
                   ` (6 preceding siblings ...)
  2014-11-23 18:55 ` brbarkstrom
@ 2014-11-23 19:30 ` brbarkstrom
  2014-11-23 22:38   ` Simon Wright
  7 siblings, 1 reply; 59+ messages in thread
From: brbarkstrom @ 2014-11-23 19:30 UTC (permalink / raw)


On Friday, November 21, 2014 6:41:45 AM UTC-5, Natasha Kerensikova wrote:
> Hello,
> 
> I happen to have found a situation in which symbolic traceback is a
> great help, but I have been a bit surprise by the (lack of) support in
> the platform to which I have access.
> 
> I have been using GNAT.Traceback.Symbolic.Symbolic_Traceback, is there a
> more portable way?
> 
> In FreeBSD, with GNAT 4.9.0, I get an output like the following, with
> the first line actually repeated about a hundred times:
> > BFD: Dwarf Error: found dwarf version '4', this reader only handles version 2 information.
> > 0x7e7773 in asis.gela.contexts.open at ??:0
> > 0x78cb43 in asis.ada_environments.open at ??:0
> > 0x46a7da in adactl at ??:0
> > 0x40690e in main at ??:0
> > 0x4069df in <_start> at ??:0
> > 0x800da3ffe in ?? at ??:0
> 
> In Debian/kFreeBSD, with GNAT 4.6, it looks like the following, which is
> what I consider as perfect:
> > 0x7fa993 in asis.ada_environments.open at asis-ada_environments.adb:241
> > 0x481a57 in adactl at adactl.adb:90
> > 0x417029 in main at b~adactl.adb:817
> > 0x8015a4347 in ?? at ??:0
> > 0x41706e in <_start> at ??:0
> 
> In Fedora 20, with GNAT 4.8.3, it looks like the following, which I find
> the worst:
> > 0x000000000069307D
> > 0x00000000004733BD
> > 0x0000000000410824
> > 0x0000003CC5A21D63
> > 0x000000000041086F
> > 0xFFFFFFFFFFFFFFFE
> 
> Considering the versions, I doubt that's the cause for the discrepancy.
> I would rather wager on something related to addr2line.
> 
> As a user, is there something I can do to improve the traceback
> representation on those platforms?
> Or is it completely in the hands of the GNAT packager/maintainer?
> 
> 
> Thanks in advance for your help,
> Natasha

Sounds like a useful design approach.  Thanks for the suggestion.
As a related question, did you need to send messages to specific
user sessions?

To pick up on the thread, how did the design deal with exceptions
and with exception diagnostics?  Any clues as to what you think
you did well and any ideas about how to do it better?

Bruce B.


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

* Re: How to get nice with GNAT?
  2014-11-23 17:41 ` brbarkstrom
  2014-11-23 19:22   ` Simon Wright
@ 2014-11-23 20:49   ` Jeffrey Carter
  2014-11-24  3:05     ` brbarkstrom
  1 sibling, 1 reply; 59+ messages in thread
From: Jeffrey Carter @ 2014-11-23 20:49 UTC (permalink / raw)


On 11/23/2014 10:41 AM, brbarkstrom@gmail.com wrote:
> 
> I'm working in GNAT GPL, so my suggestion may not work with every
> compiler.
> 
> On the other hand, in my code, the if following the exception in the
> procedure is picked up and executed properly.  The code doesn't act
> like the program has to fail if any exception is raised.

I don't think you're talking about exceptions. I took this program:

with Ada.Text_IO;
procedure Boolean_Exception is
   procedure Test (OK : out Boolean) is
      -- empty declarative part
   begin -- Test
      OK := False;

      raise Constraint_Error;
   end Test;

   OK : Boolean := True;
begin -- Boolean_Exception
   Test (OK => OK);
   Ada.Text_IO.Put_Line (Item => "No exception");
exception -- Boolean_Exception
when others =>
   Ada.Text_IO.Put_Line (Item => Boolean'Image (OK) );
end Boolean_Exception;

compiled with GNAT 4.6 on Linux, and got:

$ gnatmake -gnatwa -gnatano -O2 -fstack-check boolean_exception.adb
gcc-4.6 -c -gnatwa -gnatano -O2 -fstack-check boolean_exception.adb
boolean_exception.adb:6:10: warning: assignment to pass-by-copy formal may have
no effect
boolean_exception.adb:6:10: warning: "raise" statement may result in abnormal
return (RM 6.4.1(17))
gnatbind -x boolean_exception.ali
gnatlink boolean_exception.ali -O2 -fstack-check
$ ./boolean_exception
TRUE

What you're talking about doesn't work with GNAT.

-- 
Jeff Carter
"This school was here before you came,
and it'll be here before you go."
Horse Feathers
48


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

* Re: How to get nice with GNAT?
  2014-11-23 19:30 ` brbarkstrom
@ 2014-11-23 22:38   ` Simon Wright
  2014-11-24  2:47     ` brbarkstrom
  0 siblings, 1 reply; 59+ messages in thread
From: Simon Wright @ 2014-11-23 22:38 UTC (permalink / raw)


brbarkstrom@gmail.com writes:

> Sounds like a useful design approach.  Thanks for the suggestion.
> As a related question, did you need to send messages to specific
> user sessions?

Something has gone badly wrong with your newsreader. All your posts
(today?) quote Natasha's original posting rather than the one you appear
to be replying to.

So I'll hold off replying until I'm sure about the question you're
asking.


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

* Re: How to get nice with GNAT?
  2014-11-23 22:38   ` Simon Wright
@ 2014-11-24  2:47     ` brbarkstrom
  0 siblings, 0 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-24  2:47 UTC (permalink / raw)


On Sunday, November 23, 2014 5:38:11 PM UTC-5, Simon Wright wrote:
> brbarkstrom writes:
> 
> > Sounds like a useful design approach.  Thanks for the suggestion.
> > As a related question, did you need to send messages to specific
> > user sessions?
> 
> Something has gone badly wrong with your newsreader. All your posts
> (today?) quote Natasha's original posting rather than the one you appear
> to be replying to.
> 
> So I'll hold off replying until I'm sure about the question you're
> asking.

I apologize - I'm still getting used to the interface.  I was going back
to the first reply arrow, rather than the one from the previous item in
the thread.

What I was trying to do was clarify some of the items I expect to show
up in a Web interface that maintains multiple, concurrent user sessions
and has different messages that need to go to different users.

Bruce B.

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

* Re: How to get nice with GNAT?
  2014-11-23 20:49   ` Jeffrey Carter
@ 2014-11-24  3:05     ` brbarkstrom
  2014-11-24  6:25       ` Jeffrey Carter
  2014-11-24 17:42       ` Dennis Lee Bieber
  0 siblings, 2 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-24  3:05 UTC (permalink / raw)


On Sunday, November 23, 2014 3:49:38 PM UTC-5, Jeffrey Carter wrote:
> On 11/23/2014 10:41 AM, brbarkstrom wrote:
> > 
> > I'm working in GNAT GPL, so my suggestion may not work with every
> > compiler.
> > 
> > On the other hand, in my code, the if following the exception in the
> > procedure is picked up and executed properly.  The code doesn't act
> > like the program has to fail if any exception is raised.
> 
> I don't think you're talking about exceptions. I took this program:
> 
> with Ada.Text_IO;
> procedure Boolean_Exception is
>    procedure Test (OK : out Boolean) is
>       -- empty declarative part
>    begin -- Test
>       OK := False;
> 
>       raise Constraint_Error;
>    end Test;
> 
>    OK : Boolean := True;
> begin -- Boolean_Exception
>    Test (OK => OK);
>    Ada.Text_IO.Put_Line (Item => "No exception");
> exception -- Boolean_Exception
> when others =>
>    Ada.Text_IO.Put_Line (Item => Boolean'Image (OK) );
> end Boolean_Exception;
> 
> compiled with GNAT 4.6 on Linux, and got:
> 
> $ gnatmake -gnatwa -gnatano -O2 -fstack-check boolean_exception.adb
> gcc-4.6 -c -gnatwa -gnatano -O2 -fstack-check boolean_exception.adb
> boolean_exception.adb:6:10: warning: assignment to pass-by-copy formal may have
> no effect
> boolean_exception.adb:6:10: warning: "raise" statement may result in abnormal
> return (RM 6.4.1(17))
> gnatbind -x boolean_exception.ali
> gnatlink boolean_exception.ali -O2 -fstack-check
> $ ./boolean_exception
> TRUE
> 
> What you're talking about doesn't work with GNAT.
> 
> -- 
> Jeff Carter
> "This school was here before you came,
> and it'll be here before you go."
> Horse Feathers
> 48

Here's a rather long response to your post:

I don't think you'll get a sensible response when you try to set
Test(OK => True); or Test(OK => False) when the specification of
the procedure Test has OK as an "out" variable.  It doesn't make 
sense try to set this value as input to a variable that emerges from the procedure (Test).

Here's a slight rewriting of the code you provided:

with Ada.Text_IO;
procedure exception_handling_0 is

   procedure test (OK : out Boolean) is
      -- empty declarative part
   begin -- test
      OK := False;
      raise Constraint_Error;
   end test;

   OK : Boolean := True;

begin -- exception_handling_0
   test (OK => OK);
   Ada.Text_IO.Put_Line (Item => "No exception");

exception
   when others =>
      Ada.Text_IO.Put_Line (Item => Boolean'Image (OK) );
end exception_handling_0;

The GNAT GPL GPS tool on my Ubuntu 14.04 LTS system returns the
two warnings:
7.10     warning: assignment to pass-by-copy formal may have no effect
7.10     warning: "raise" statement may result in abnormal return
           (RM 6.4.1(17))

In other words, a programmer shouldn't expect a variable input to
an "out" variable in the interface specification to have any relation
to whatever is generated in the procedure that is called.  Secondly,
an exception raised in the procedure test may result in an abnormal
return.  This is hardly a clean piece of code. 

When I run it, the output from the code does something that seems
to me to be an abnormal return.  It returns the output "TRUE".
The output claims that "the process terminated successfully, ...".  
It certainly isn't the expected behavior in a reasonable reading of the 
procedure text.  Rather it suggests that the compiler completely ignored
whatever went on in the procedure.

Putting the same code into a Windows XP installation of GNAT GPL 2014 with GPS
produces exactly the same warnings, compilation, and output.

In the original source code I provided, I used the following specification
file (called Common_Defs.ads):

with Ada.Characters.Latin_1;
with Ada.Strings;
with Ada.Strings.Bounded;
with Ada.Numerics;
with Ada.Numerics.generic_elementary_functions;

package Common_Defs is
  ------------------------------------------------------------------------------
  -- Generic Packages
  ------------------------------------------------------------------------------
  subtype real        is long_float;
  package Usr_Math    is new
                        Ada.Numerics.generic_elementary_functions(real);
  Std_Vstring_Length  : constant :=  256;
  package VString     is new
                        Ada.Strings.Bounded.Generic_Bounded_Length(Std_Vstring_Length);
  Long_Vstring_Lngth  : constant := 5000;
  package Long_Vstring is new
                        Ada.Strings.Bounded.Generic_Bounded_Length(Long_Vstring_Lngth);
  ------------------------------------------------------------------------------
  -- Constant
  ------------------------------------------------------------------------------
   TAB                         : constant Character := Ada.Characters.Latin_1.HT;
end Common_Defs;

Then, I created the source code

with Ada.Text_IO;
with Common_Defs; use Common_Defs;
procedure Test_Exception is

   -- Local Procedure Specification
   procedure Test (I       : in     Natural;
                   OK      :    out Boolean;
                   Err_Msg :    out Vstring.Bounded_String);

   -- Variables
   I       : Natural := 20;
   Test_OK : Boolean;
   Err_Msg : Vstring.Bounded_String;

   -- Local Procedure Body
   procedure Test (I       : in     Natural;
                   OK      :    out Boolean;
                   Err_Msg :    out Vstring.Bounded_String) is
      Max_I          : Natural := 10;
      I_Out_Of_Range : exception;      
   begin -- Test
      OK := False;
      Err_Msg := Vstring.To_Bounded_String("procedure Test was not initialized when this message was created.");
      if I <= Max_I then
         OK := True;
         Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
         Err_Msg := Vstring.Append(Err_Msg, " was less than or equal to ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
      else
         raise I_Out_Of_Range;
      end if;
   exception
      when I_Out_Of_Range =>
         Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
         Err_Msg := Vstring.Append(Err_Msg, " was greater than ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
         Err_Msg := Vstring.Append(Err_Msg, " which raises the constraint 'I_Out_Of_Range'.");
      when others =>
         Err_Msg := Vstring.To_Bounded_String("In procedure Test, something unexpected happened.");
   end Test;

begin -- Test_Exception
   Test (I       => 25,
         OK      => Test_OK,
         Err_Msg => Err_Msg);
   if Test_OK then
      Ada.Text_IO.Put_Line(Vstring.To_String(Err_Msg));
   else
      Ada.Text_IO.Put_Line(Vstring.To_String(Err_Msg));
   end if;
end Test_Exception; 

On Windows, this compiles without warnings.  After compilation, binding, and linking, it
runs and outputs the message 
"In procedure Test, I as input :  25 was greater than  10 which raises the constraint 'I_Out_Of_Range'."  It is clear that the initial setting of
OK and Err_Msg in the procedure have been changed as a result of the
operations during execution.

The behavior on the Ubuntu Linux 64-bit installation of GNAT GPL is identical.

My conclusions:

1.  One should not call a procedure to input an "out" variable as declared in the spec and
expect it to return values from the interior of the procedure.  In this code, the exception is not one of the system exceptions.
Rather, it is one declared normally in accord with the RM (11.1).  An exception handler follows the
specification in RM (11.2), where the Examples at the end of this definition show an approach
that the code I've provided follows.

2.  The handled sequence of statements allow variables set as "out" in the procedure specification
to appear as legitimate values (even using the "pass-by-copy" rule).  Thus, these "out" variables
can guide procedure actions for the calling procedure even when the called
procedure throws an exception.

Bruce B.


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

* Re: How to get nice with GNAT?
  2014-11-24  3:05     ` brbarkstrom
@ 2014-11-24  6:25       ` Jeffrey Carter
  2014-11-24 14:39         ` brbarkstrom
  2014-11-24 17:42       ` Dennis Lee Bieber
  1 sibling, 1 reply; 59+ messages in thread
From: Jeffrey Carter @ 2014-11-24  6:25 UTC (permalink / raw)


On 11/23/2014 08:05 PM, brbarkstrom@gmail.com wrote:
> 
> I don't think you'll get a sensible response when you try to set
> Test(OK => True); or Test(OK => False) when the specification of
> the procedure Test has OK as an "out" variable.  It doesn't make 
> sense try to set this value as input to a variable that emerges from the procedure (Test).

I think it's clear you have no idea what you're talking about. I set OK to True
before calling Test so that I could demonstrate that Test did not modify that value.

> The GNAT GPL GPS tool on my Ubuntu 14.04 LTS system returns the
> two warnings:
> 7.10     warning: assignment to pass-by-copy formal may have no effect
> 7.10     warning: "raise" statement may result in abnormal return
>            (RM 6.4.1(17))
> 
> In other words, a programmer shouldn't expect a variable input to
> an "out" variable in the interface specification to have any relation
> to whatever is generated in the procedure that is called.  Secondly,
> an exception raised in the procedure test may result in an abnormal
> return.  This is hardly a clean piece of code. 

This warning is saying that the assignment to the formal parameter OK in Test
(the "pass-by-copy formal") won't do anything because the formal is not copied
back to the actual when the procedure propagates an exception. It has nothing to
do with setting the variable OK to True.

> When I run it, the output from the code does something that seems
> to me to be an abnormal return.  It returns the output "TRUE".

Test does not return True. OK had the value True before the call, and it still
has the value True after the call because the assignment to the formal parameter
OK in True has no effect. This is what I was trying to demonstrate.

>    procedure Test (I       : in     Natural;
>                    OK      :    out Boolean;
>                    Err_Msg :    out Vstring.Bounded_String) is
>       Max_I          : Natural := 10;
>       I_Out_Of_Range : exception;      
>    begin -- Test
>       OK := False;
>       Err_Msg := Vstring.To_Bounded_String("procedure Test was not initialized when this message was created.");
>       if I <= Max_I then
>          OK := True;
>          Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
>          Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
>          Err_Msg := Vstring.Append(Err_Msg, " was less than or equal to ");
>          Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
>       else
>          raise I_Out_Of_Range;
>       end if;
>    exception
>       when I_Out_Of_Range =>
>          Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
>          Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
>          Err_Msg := Vstring.Append(Err_Msg, " was greater than ");
>          Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
>          Err_Msg := Vstring.Append(Err_Msg, " which raises the constraint 'I_Out_Of_Range'.");
>       when others =>
>          Err_Msg := Vstring.To_Bounded_String("In procedure Test, something unexpected happened.");
>    end Test;

This procedure never propagates an exception. It returns normally in all cases.
As I said, you are not talking about exceptions in the calling code. You're
talking about returning error codes and checking them after the call. This has
all of the problems with returning error codes known from over 4 decades of
using C. These problems led to the inclusion of exceptions in more modern
languages; writing "C in Ada" is a step backwards.

-- 
Jeff Carter
"I'm particularly glad that these lovely children were
here today to hear that speech. Not only was it authentic
frontier gibberish, it expressed a courage little seen
in this day and age."
Blazing Saddles
88


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

* Re: How to get nice with GNAT?
  2014-11-24  6:25       ` Jeffrey Carter
@ 2014-11-24 14:39         ` brbarkstrom
  0 siblings, 0 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-24 14:39 UTC (permalink / raw)


On Monday, November 24, 2014 1:25:42 AM UTC-5, Jeffrey Carter wrote:
> On 11/23/2014 08:05 PM, brbarkstrom wrote:
> > 
> > I don't think you'll get a sensible response when you try to set
> > Test(OK => True); or Test(OK => False) when the specification of
> > the procedure Test has OK as an "out" variable.  It doesn't make 
> > sense try to set this value as input to a variable that emerges from the procedure (Test).
> 
> I think it's clear you have no idea what you're talking about. I set OK to True
> before calling Test so that I could demonstrate that Test did not modify that value.
> 
> > The GNAT GPL GPS tool on my Ubuntu 14.04 LTS system returns the
> > two warnings:
> > 7.10     warning: assignment to pass-by-copy formal may have no effect
> > 7.10     warning: "raise" statement may result in abnormal return
> >            (RM 6.4.1(17))
> > 
> > In other words, a programmer shouldn't expect a variable input to
> > an "out" variable in the interface specification to have any relation
> > to whatever is generated in the procedure that is called.  Secondly,
> > an exception raised in the procedure test may result in an abnormal
> > return.  This is hardly a clean piece of code. 
> 
> This warning is saying that the assignment to the formal parameter OK in Test
> (the "pass-by-copy formal") won't do anything because the formal is not copied
> back to the actual when the procedure propagates an exception. It has nothing to
> do with setting the variable OK to True.
> 
> > When I run it, the output from the code does something that seems
> > to me to be an abnormal return.  It returns the output "TRUE".
> 
> Test does not return True. OK had the value True before the call, and it still
> has the value True after the call because the assignment to the formal parameter
> OK in True has no effect. This is what I was trying to demonstrate.
> 
> >    procedure Test (I       : in     Natural;
> >                    OK      :    out Boolean;
> >                    Err_Msg :    out Vstring.Bounded_String) is
> >       Max_I          : Natural := 10;
> >       I_Out_Of_Range : exception;      
> >    begin -- Test
> >       OK := False;
> >       Err_Msg := Vstring.To_Bounded_String("procedure Test was not initialized when this message was created.");
> >       if I <= Max_I then
> >          OK := True;
> >          Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
> >          Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
> >          Err_Msg := Vstring.Append(Err_Msg, " was less than or equal to ");
> >          Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
> >       else
> >          raise I_Out_Of_Range;
> >       end if;
> >    exception
> >       when I_Out_Of_Range =>
> >          Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
> >          Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
> >          Err_Msg := Vstring.Append(Err_Msg, " was greater than ");
> >          Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
> >          Err_Msg := Vstring.Append(Err_Msg, " which raises the constraint 'I_Out_Of_Range'.");
> >       when others =>
> >          Err_Msg := Vstring.To_Bounded_String("In procedure Test, something unexpected happened.");
> >    end Test;
> 
> This procedure never propagates an exception. It returns normally in all cases.
> As I said, you are not talking about exceptions in the calling code. You're
> talking about returning error codes and checking them after the call. This has
> all of the problems with returning error codes known from over 4 decades of
> using C. These problems led to the inclusion of exceptions in more modern
> languages; writing "C in Ada" is a step backwards.
> 
> -- 
> Jeff Carter
> "I'm particularly glad that these lovely children were
> here today to hear that speech. Not only was it authentic
> frontier gibberish, it expressed a courage little seen
> in this day and age."
> Blazing Saddles
> 88

Here's a slight modification to the procedure you provided:

with Ada.Text_IO;
procedure exception_handling_1 is

   procedure test (OK : out Boolean) is
      -- empty declarative part
   begin -- test
      OK := True;
      raise Constraint_Error;
--     exception
--        when Constraint_Error =>
--           OK := False;
   end test;

   OK : Boolean := True;

begin -- exception_handling_1
   test (OK => OK);
   Ada.Text_IO.Put_Line (Item => "No exception");
   Ada.Text_IO.Put_Line (Item => Boolean'Image (OK) );

exception
   when others =>
      Ada.Text_IO.Put_Line (Item => Boolean'Image (OK) );
end exception_handling_1; 

When the exception handling section in the procedure test
is commented out, the compiler returns the same pair of
warning messages.  When the program runs, the exception prevents
the test procedure from completing.  Then, the unhandled
exception propagates up to the calling procedure and the
"when others" exception in that procedure executes and
does not modify the value of OK that was set in calling test.

When the exception handling section in the procedure test
is not commented out, the compiler has no warning messages.
When the program runs, test now raises the "Constraint_Error"
after the internal value of OK is set to TRUE.  The now-included 
exception handler sets OK in the procedure to FALSE and completes.
Upon completing the test procedure, control returns to the
calling procedure.  Since test handled the exception, the
calling procedure does not receive the exception and terminates
normally, printing the note "No exception", followed by the 
changed value of OK, which is now "FALSE".  In other words,
a called procedure that has its own exception handling can
change the value of parameters in its interface and propagate
the changes back to the calling procedure.

I believe the proper lesson from this is that called procedures can 
handle exceptions and pass back diagnostic information about
what led to the exception.  The choice of where to handle the
exception is up to the code designer.  Sometimes it may be
appropriate to handle the exception in the called procedure.
If this is the selected strategy, then the called procedure can
modify and return the "out" or "inout" variables.  If the exception
is handled in the called procedure, then it does not raise an
exception in the calling procedure.  If the called procedure
does not handle the exception, the exception is propagated up to the 
calling procedure.

Bruce B.

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

* Re: How to get nice with GNAT?
  2014-11-24  3:05     ` brbarkstrom
  2014-11-24  6:25       ` Jeffrey Carter
@ 2014-11-24 17:42       ` Dennis Lee Bieber
  2014-11-25 13:45         ` brbarkstrom
  1 sibling, 1 reply; 59+ messages in thread
From: Dennis Lee Bieber @ 2014-11-24 17:42 UTC (permalink / raw)


On Sun, 23 Nov 2014 19:05:18 -0800 (PST), brbarkstrom@gmail.com declaimed
the following:


>
>The GNAT GPL GPS tool on my Ubuntu 14.04 LTS system returns the
>two warnings:
>7.10     warning: assignment to pass-by-copy formal may have no effect
>7.10     warning: "raise" statement may result in abnormal return
>           (RM 6.4.1(17))
>
>In other words, a programmer shouldn't expect a variable input to
>an "out" variable in the interface specification to have any relation
>to whatever is generated in the procedure that is called.  Secondly,
>an exception raised in the procedure test may result in an abnormal
>return.  This is hardly a clean piece of code. 
>
>When I run it, the output from the code does something that seems
>to me to be an abnormal return.  It returns the output "TRUE".
>The output claims that "the process terminated successfully, ...".  
>It certainly isn't the expected behavior in a reasonable reading of the 
>procedure text.  Rather it suggests that the compiler completely ignored
>whatever went on in the procedure.
>

	I would interpret it to mean that the raise statement aborted the
function "test" before the copying of the "FALSE" value into the return
structure on the stack, so the main procedure never sees the value change.

	If scalar's are handled as locals that are copied from the passed
parameters on input and then copied back upon (normal) exit -- this makes
sense.

	The last paragraph of the (2005) Reference Manual, section 6.4.1
Parameter Associations reads:

After normal completion and leaving of a subprogram, for each IN OUT or OUT
parameter that is passed by copy, the value of the formal parameter is
converted to the subtype of the variable given as the actual parameter and
assigned to it.

	Note that: "after normal completion and leaving ... and assigned to
it".

	The raise is not "normal completion", and thereby may not perform the
"assign".
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/


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

* Re: How to get nice traceback with GNAT?
  2014-11-22  9:45   ` How to get nice traceback " Natasha Kerensikova
  2014-11-22  9:57     ` Dmitry A. Kazakov
@ 2014-11-24 22:35     ` Randy Brukardt
  1 sibling, 0 replies; 59+ messages in thread
From: Randy Brukardt @ 2014-11-24 22:35 UTC (permalink / raw)


"Natasha Kerensikova" <lithiumcat@instinctive.eu> wrote in message 
news:slrnm70mph.nrc.lithiumcat@nat.rebma.instinctive.eu...
> On 2014-11-21, Randy Brukardt <randy@rrsoftware.com> wrote:
...
>> No, perfect is:
>> ** Unhandled CONSTRAINT_ERROR
>>    Index or Subtype out of bounds - Pos of Error Value = -1
>> On Line Number 484 In 
>> J2TYPE_PROFILE_CHECKING.END_SPEC_AND_DO_DELAYED_THUNKS
>> Called from line number 1914 In J2SEMANTIC_ROUTINES.SEMANTICS
>> Called from line number 466 In JANUS2.SEMDRIVER
>> Called from line number 527 In JANUS2
>
> It might be nitpicking, but as far as the traceback (word I
> unfortunately missed in the subject) you actually provide less
> information: GNAT has function name, file name, line number, while yours
> lacks the file name (might be easy to find out, but that's still a
> mental overhead nonetheless).

You're right, of course, but in our defense it wasn't necessary on the CP/M 
and MS-DOS systems this was originally defined for. The file name was always 
the first 8 characters of the package name, and indeed the editor we used 
automatically truncated the names, so
    edit J2TYPE_PROFILE_CHECKING.adb
would open the right file without any mental energy.

Indeed, this is something that the programming environment should do for you 
(it knows the package to file name correspondence), so there's no real need 
for the file name to be in the trackback. (We wouldn't have wanted to store 
the file names in the object code, as they would waste a lot of space.)

> As far as the exception message goes, I agree that yours is quite
> impressive. I didn't mention it in the OP because I'm actually chasing
> user exceptions (explicit raise statements), so I have the power to
> improve the exception message. Compare to the traceback, which is to
> tied to the compiler internals that a mere user has no power to improve
> anything. I can't even guess what is going in GNAT to get so wildly
> different outputs on different platforms.

Right, although of course you have no control over the exception message for 
language-defined checks, either. And those are the ones you're usually 
debugging.

                                         Randy.


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

* Re: How to get nice with GNAT?
  2014-11-24 17:42       ` Dennis Lee Bieber
@ 2014-11-25 13:45         ` brbarkstrom
  2014-11-25 15:07           ` ake.ragnar.dahlgren
  2014-11-25 18:33           ` Dennis Lee Bieber
  0 siblings, 2 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-25 13:45 UTC (permalink / raw)


On Monday, November 24, 2014 12:42:23 PM UTC-5, Dennis Lee Bieber wrote:
> On Sun, 23 Nov 2014 19:05:18 -0800 (PST), brbarkstrom declaimed
> the following:
> 
> 
> >
> >The GNAT GPL GPS tool on my Ubuntu 14.04 LTS system returns the
> >two warnings:
> >7.10     warning: assignment to pass-by-copy formal may have no effect
> >7.10     warning: "raise" statement may result in abnormal return
> >           (RM 6.4.1(17))
> >
> >In other words, a programmer shouldn't expect a variable input to
> >an "out" variable in the interface specification to have any relation
> >to whatever is generated in the procedure that is called.  Secondly,
> >an exception raised in the procedure test may result in an abnormal
> >return.  This is hardly a clean piece of code. 
> >
> >When I run it, the output from the code does something that seems
> >to me to be an abnormal return.  It returns the output "TRUE".
> >The output claims that "the process terminated successfully, ...".  
> >It certainly isn't the expected behavior in a reasonable reading of the 
> >procedure text.  Rather it suggests that the compiler completely ignored
> >whatever went on in the procedure.
> >
> 
> 	I would interpret it to mean that the raise statement aborted the
> function "test" before the copying of the "FALSE" value into the return
> structure on the stack, so the main procedure never sees the value change.
> 
> 	If scalar's are handled as locals that are copied from the passed
> parameters on input and then copied back upon (normal) exit -- this makes
> sense.
> 
> 	The last paragraph of the (2005) Reference Manual, section 6.4.1
> Parameter Associations reads:
> 
> After normal completion and leaving of a subprogram, for each IN OUT or OUT
> parameter that is passed by copy, the value of the formal parameter is
> converted to the subtype of the variable given as the actual parameter and
> assigned to it.
> 
> 	Note that: "after normal completion and leaving ... and assigned to
> it".
> 
> 	The raise is not "normal completion", and thereby may not perform the
> "assign".
> -- 
> 	Wulfraed                 Dennis Lee Bieber         AF6VN

If an exception is raised, section 11.4 of the RM comes into play.  11.4(1)
says that when an exception is raised, normal program execution is abandoned
and control is transferred to an applicable exception handler, if any.  Note
also section 11.4(7) which allows an exception handler to carry on assigning
variables, including ones that can be passed out.  When the exception handler
works, it lowers the exception and prevents propagation to the calling
procedure.  Thus, it is perfectly acceptable for the handler to assign
an "out" variable, which will be passed out.

In other words,

1) No exception is raised: pass-by-copy variables appear in the calling
procedure with the last value assigned before the called procedure exits;
there is no exception propagated back to the caller.

2) An exception is raised without an exception handler in the called procedure:
the exception is propagated back to the caller.  I believe a pass-by-copy
parameter that is an "out" parameter in the interface propagates out to the
caller with the last assigned value.

3) An exception is raised with an exception handler in the called procedure:
the exception is lowered and not propagated to the caller.  The exception
handling code can assign a legal value to an "out" parameter and it will appear
in the calling procedure with that value.

4) An exception is raised with an exception handler in the called procedure,
but the exception handler contains a raise; statement: the exception is reraised
and will be propagated back to the caller.  The exception handling code can
assign a legal value to an "out" parameter before the exception is re-raised,
in which case the new assignment will appear in the calling procedure.

5) The Exceptions Package of part 11.4.1 offers ready-made functions 
and procedures that can reduce programming effort.

These behaviors are consistent with what I've observed in the execution of the
compiled versions of the code I provided in previous posts.  I think the only
question about whether different compilers would implement this behavior is
item 2), although I have not been able to find a clear statement in RM as
to whether not passing back a pass-by-copy value is left to the implementer
in the event of the exception being raised.

Bruce B.


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

* Re: How to get nice with GNAT?
  2014-11-25 13:45         ` brbarkstrom
@ 2014-11-25 15:07           ` ake.ragnar.dahlgren
  2014-11-25 15:51             ` brbarkstrom
                               ` (3 more replies)
  2014-11-25 18:33           ` Dennis Lee Bieber
  1 sibling, 4 replies; 59+ messages in thread
From: ake.ragnar.dahlgren @ 2014-11-25 15:07 UTC (permalink / raw)


Hello everybody,

This Ada gem is related to this discussion (and I just point it out since I didn't see it pointed out earlier)
http://www.adacore.com/adaanswers/gems/gem-150out-and-uninitialized/

Of course I always listen seriously to Jeff Carter but it's not obvious to me that doing "C in Ada" is bad. If I remember correctly Google employees are recommended to avoid using exceptions when doing C++. The designers of Google Go has gone great lengths to avoid the exception concept as much as possible. In addition SPARK forbids usage of exceptions.

@Natasha: Sorry, don't have any useful input to you. But thanks for starting this discussion topic, and thanks for all input from everybody participating!

Best regards,
Åke Ragnar Dahlgren

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

* Re: How to get nice with GNAT?
  2014-11-25 15:07           ` ake.ragnar.dahlgren
@ 2014-11-25 15:51             ` brbarkstrom
  2014-11-25 16:52             ` Jeffrey Carter
                               ` (2 subsequent siblings)
  3 siblings, 0 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-25 15:51 UTC (permalink / raw)


On Tuesday, November 25, 2014 10:07:04 AM UTC-5, ake.ragna... wrote:
> Hello everybody,
> 
> This Ada gem is related to this discussion (and I just point it out since I didn't see it pointed out earlier)
> http://www.adacore.com/adaanswers/gems/gem-150out-and-uninitialized/
> 
> Of course I always listen seriously to Jeff Carter but it's not obvious to me that doing "C in Ada" is bad. If I remember correctly Google employees are recommended to avoid using exceptions when doing C++. The designers of Google Go has gone great lengths to avoid the exception concept as much as possible. In addition SPARK forbids usage of exceptions.
> 
> @Natasha: Sorry, don't have any useful input to you. But thanks for starting this discussion topic, and thanks for all input from everybody participating!
> 
> Best regards,
> Åke Ragnar Dahlgren

Note that the Local procedure in the Gem does not contain an exception 
handler.  If it did, the "out" variable could be set to something sensible.  
The exception would be lowered and not propagated to the calling procedure.
In that situation, the calling program might or might not even be aware
of the exception except for the value of the variable copied out.

The Gem does clarify how an unhandled exception would work.  I appreciate
that clarification.  Thanks.

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

* Re: How to get nice with GNAT?
  2014-11-25 15:07           ` ake.ragnar.dahlgren
  2014-11-25 15:51             ` brbarkstrom
@ 2014-11-25 16:52             ` Jeffrey Carter
  2014-11-25 19:18             ` G.B.
  2014-11-25 22:12             ` Randy Brukardt
  3 siblings, 0 replies; 59+ messages in thread
From: Jeffrey Carter @ 2014-11-25 16:52 UTC (permalink / raw)


On 11/25/2014 08:07 AM, ake.ragnar.dahlgren@gmail.com wrote:
> 
> Of course I always listen seriously to Jeff Carter but it's not obvious to me
> that doing "C in Ada" is bad. If I remember correctly Google employees are
> recommended to avoid using exceptions when doing C++. The designers of Google
> Go has gone great lengths to avoid the exception concept as much as possible.

We have decades of experience with C that shows that humans cannot use it safely
on real-world problems. Ignoring error codes is part of that problem. I think
it's clear the C mind set should not be emulated. As to Google and Go, if they
were worth listening to, they'd be using Ada :)

> In addition SPARK forbids usage of exceptions.

SPARK also requires proof that exceptions won't occur, and proof that error
codes are not ignored. C would be a much better language if it required proof
that error codes are not ignored, and arrays are never indexed past their
bounds, and proof ...

-- 
Jeff Carter
"I was in love with a beautiful blonde once, dear.
She drove me to drink. That's the one thing I'm
indebted to her for."
Never Give a Sucker an Even Break
109

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

* Re: How to get nice with GNAT?
  2014-11-25 13:45         ` brbarkstrom
  2014-11-25 15:07           ` ake.ragnar.dahlgren
@ 2014-11-25 18:33           ` Dennis Lee Bieber
  2014-11-26  1:27             ` Dennis Lee Bieber
  1 sibling, 1 reply; 59+ messages in thread
From: Dennis Lee Bieber @ 2014-11-25 18:33 UTC (permalink / raw)


On Tue, 25 Nov 2014 05:45:45 -0800 (PST), brbarkstrom@gmail.com declaimed
the following:


>2) An exception is raised without an exception handler in the called procedure:
>the exception is propagated back to the caller.  I believe a pass-by-copy
>parameter that is an "out" parameter in the interface propagates out to the
>caller with the last assigned value.
>

	<SNIP>

>These behaviors are consistent with what I've observed in the execution of the
>compiled versions of the code I provided in previous posts.  I think the only
>question about whether different compilers would implement this behavior is
>item 2), although I have not been able to find a clear statement in RM as
>to whether not passing back a pass-by-copy value is left to the implementer
>in the event of the exception being raised.

	Have to dig up some ancient history...

http://archive.adaic.com/standards/83rat/html/ratl-08-02.html#8.2.3
"""
If the execution of a subprogram is abandoned as the result of an exception
not handled locally, then the final value of an actual parameter that is
associated with a formal parameter of mode in out may depend on the
parameter passing mechanism: If by copy, the final value will still be the
initial value before the call.
"""

Does leave OUT only parameters hanging, unless one just takes the view that
IN OUT and OUT both rely upon copying from procedure local memory to return
parameter memory at the same point (and an IN OUT copies from the parameter
memory to local memory upon entry).

"""
The allowed mechanisms follow from the above considerations.

	a.	For scalar types, and for all modes, all parameter passing must be
achieved by copy. The same treatment applies to access types, for the
reasons given in the previous section. 

	b.	For record and array types, the language does not specify whether
parameter passing is achieved by reference or by copy. ...
"""
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/


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

* Re: How to get nice with GNAT?
  2014-11-25 15:07           ` ake.ragnar.dahlgren
  2014-11-25 15:51             ` brbarkstrom
  2014-11-25 16:52             ` Jeffrey Carter
@ 2014-11-25 19:18             ` G.B.
  2014-11-25 20:47               ` brbarkstrom
  2014-11-25 22:12             ` Randy Brukardt
  3 siblings, 1 reply; 59+ messages in thread
From: G.B. @ 2014-11-25 19:18 UTC (permalink / raw)


On 25.11.14 16:07, ake.ragnar.dahlgren@gmail.com wrote:
> Of course I always listen seriously to Jeff Carter but it's not obvious to me that doing "C in Ada" is bad. If I remember correctly Google employees are recommended to avoid using exceptions when doing C++. The designers of Google Go has gone great lengths to avoid the exception concept as much as possible. In addition SPARK forbids usage of exceptions.

Tucker Taft, designer of both Ada 95 and ParaSail has not
put Ada's exceptions in his ParaSail language(*). The latter
language does presume a lot of checking at compile time, though,
of logical expressions etc.; all of this is almost entirely absent
from C programs.

That's not without consequences for a fair comparison.

Some static analyzers re-interpret the C language by adding
rules and information that is not present in either C programs
or in the C language. The interpretation may likely be what
the programmers would have intended, but still inference cannot
magically add all of the same logical information to a C program
that would be present in a ParaSail program. Moreover, a program's
meaning then begins to essentially depend on the QoI of a compiler,
not on the language or on your own expressions as a program's author.

As these and previous efforts both at language design and
at compiler technology will influence AdaCore, it seems likely
that Ada 2012's contracts can both reduce the need for checks
at run-time and add assurance based on real expressions,
while also improving diagnostic messages if provers look at
the assertions, the calls, and the implementations.

There are the beginnings specific mentions of exception
identifiers in post-conditions, IIUC.

    Post => that_will_be_true(...) or else raise  ...;

ParaSail...
"eliminates run-time exception handling -- strong compile-time
  checking of preconditions and support for parallel event-handling
  provides a safer alternative;"

__
(*)https://forge.open-do.org/plugins/moinmoin/parasail/


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

* Re: How to get nice with GNAT?
  2014-11-25 19:18             ` G.B.
@ 2014-11-25 20:47               ` brbarkstrom
  0 siblings, 0 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-25 20:47 UTC (permalink / raw)


On Tuesday, November 25, 2014 2:18:21 PM UTC-5, G.B. wrote:
> On 25.11.14 16:07, ake.ragnar.dahlgren wrote:
> > Of course I always listen seriously to Jeff Carter but it's not obvious to me that doing "C in Ada" is bad. If I remember correctly Google employees are recommended to avoid using exceptions when doing C++. The designers of Google Go has gone great lengths to avoid the exception concept as much as possible. In addition SPARK forbids usage of exceptions.
> 
> Tucker Taft, designer of both Ada 95 and ParaSail has not
> put Ada's exceptions in his ParaSail language(*). The latter
> language does presume a lot of checking at compile time, though,
> of logical expressions etc.; all of this is almost entirely absent
> from C programs.
> 
> That's not without consequences for a fair comparison.
> 
> Some static analyzers re-interpret the C language by adding
> rules and information that is not present in either C programs
> or in the C language. The interpretation may likely be what
> the programmers would have intended, but still inference cannot
> magically add all of the same logical information to a C program
> that would be present in a ParaSail program. Moreover, a program's
> meaning then begins to essentially depend on the QoI of a compiler,
> not on the language or on your own expressions as a program's author.
> 
> As these and previous efforts both at language design and
> at compiler technology will influence AdaCore, it seems likely
> that Ada 2012's contracts can both reduce the need for checks
> at run-time and add assurance based on real expressions,
> while also improving diagnostic messages if provers look at
> the assertions, the calls, and the implementations.
> 
> There are the beginnings specific mentions of exception
> identifiers in post-conditions, IIUC.
> 
>     Post => that_will_be_true(...) or else raise  ...;
> 
> ParaSail...
> "eliminates run-time exception handling -- strong compile-time
>   checking of preconditions and support for parallel event-handling
>   provides a safer alternative;"
> 
> __
> (*)https://forge.open-do.org/plugins/moinmoin/parasail/

Thanks to the last two posters for clarifying the situation with
references to documents I haven't consulted.  For now, it looks like
raising exceptions and using exception handlers is quite legal.
In the code development I'm doing, these tools are helpful and
fairly easy to understand.  Personally, I don't like to have code
that raises warnings.  Thus, when using a local exception handler
removes the two warnings that appear when there isn't a handler,
I feel more confident that the code will work.

Bruce B.


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

* Re: How to get nice with GNAT?
  2014-11-25 15:07           ` ake.ragnar.dahlgren
                               ` (2 preceding siblings ...)
  2014-11-25 19:18             ` G.B.
@ 2014-11-25 22:12             ` Randy Brukardt
  2014-11-25 23:30               ` Simon Wright
  2014-11-26  8:41               ` Dmitry A. Kazakov
  3 siblings, 2 replies; 59+ messages in thread
From: Randy Brukardt @ 2014-11-25 22:12 UTC (permalink / raw)


<ake.ragnar.dahlgren@gmail.com> wrote in message 
news:8f203a9a-6c7c-4614-bc7d-efa65bf10776@googlegroups.com...
>Of course I always listen seriously to Jeff Carter but it's not obvious to 
>me that doing
>"C in Ada" is bad.

It's bad. :-)

> If I remember correctly Google employees are recommended to avoid using 
> exceptions
>when doing C++. The designers of Google Go has gone great lengths to avoid 
>the exception
>concept as much as possible.

Very bad advice, IMHO. With one exception (pun intended):

> In addition SPARK forbids usage of exceptions.

While I think SPARK would be better served with limited exception support, 
at least they require a proof that no exceptions can be raised.

The reason I feel so strongly about this is that exceptions (especially 
Constraint_Error and Program_Error) point out bugs in your code. Whenever 
you "eat" an exception (turning it into an error code, or simply ignoring 
it), you've put an opportunity to ignore a bug into your code. With all of 
the potential problems that entails.

To take a concrete example. My web server runs with all exceptions enabled, 
and there is very little handling of exceptions (there are a few cases where 
expected exceptions are handled, as when a TCP/IP connection is unexpectedly 
dropped). Mainly, the worker tasks handle any surprise exceptions, log them, 
and reset everything in that task to a fresh state. Doing this prevents most 
bugs from causing security problems -- while a crafted input might cause one 
worker to fail, that only causes the sender to get no response. Other 
connections (workers) are uneffected, and there is almost no chance of a 
detected bug from overwriting memory or disk or any of the other things that 
cause security problems.

Exceptions surely aren't enough to prevent all security issues, but they can 
help avoid a substantial number of them.

(As previously noted, if you could prove that no exceptions are possible - 
meaning that no low-level bugs are possible - that would be better than 
having to figure out last-chance handlers and the like, but that's still 
beyond the state of the art for general purpose code. When that changes, 
I'll reconsider my stance on exceptions, but not until then.)

                                                  Randy.



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

* Re: How to get nice with GNAT?
  2014-11-25 22:12             ` Randy Brukardt
@ 2014-11-25 23:30               ` Simon Wright
  2014-11-26  1:25                 ` G.B.
  2014-11-26  6:18                 ` J-P. Rosen
  2014-11-26  8:41               ` Dmitry A. Kazakov
  1 sibling, 2 replies; 59+ messages in thread
From: Simon Wright @ 2014-11-25 23:30 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> The reason I feel so strongly about this is that exceptions
> (especially Constraint_Error and Program_Error) point out bugs in your
> code. Whenever you "eat" an exception (turning it into an error code,
> or simply ignoring it), you've put an opportunity to ignore a bug into
> your code. With all of the potential problems that entails.

We discovered that some misguided people had used

   exception
      when others => null;
   end;

and I had the fun of using ASIS to check the whole application for this
pattern via ASIS2XML and an xslt-based report.

Today I expect we'd use AdaControl. I have to say I don't remember
whether we could have then (probably about 2007).


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

* Re: How to get nice with GNAT?
  2014-11-25 23:30               ` Simon Wright
@ 2014-11-26  1:25                 ` G.B.
  2014-11-26  7:35                   ` Simon Wright
  2014-11-26  6:18                 ` J-P. Rosen
  1 sibling, 1 reply; 59+ messages in thread
From: G.B. @ 2014-11-26  1:25 UTC (permalink / raw)


Simon Wright <simon@pushface.org> wrote:
.
> 
> We discovered that some misguided people had used
> 
>    exception
>       when others => null;
>    end;

The guidance that code like a silencing exception handler
can be following may be orienting towards presentational
flawlessness (polish). When demonstrating a program, the
audience can include hounds. Then
either the program must appear to them to be without flaw,
which in case of exceptions on the screen it isn't. Or,
the presenter must be capable of silencing rhetoric.
Otherwise, the hounds will snap and the presenter is
going to be a toy.

A business attitude suggests this kind of reasoning to less
technically minded, but all the more simple-minded strategists.


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

* Re: How to get nice with GNAT?
  2014-11-25 18:33           ` Dennis Lee Bieber
@ 2014-11-26  1:27             ` Dennis Lee Bieber
  2014-11-26  3:29               ` brbarkstrom
  0 siblings, 1 reply; 59+ messages in thread
From: Dennis Lee Bieber @ 2014-11-26  1:27 UTC (permalink / raw)


On Tue, 25 Nov 2014 13:33:01 -0500, Dennis Lee Bieber
<wlfraed@ix.netcom.com> declaimed the following:


>
>Does leave OUT only parameters hanging, unless one just takes the view that
>IN OUT and OUT both rely upon copying from procedure local memory to return
>parameter memory at the same point (and an IN OUT copies from the parameter
>memory to local memory upon entry).
>

	ADDENDUM: Original Ada OUT parameters were write-only from the
viewpoint of the procedure too... Ada 95 allowed them to be used as
read-write within the procedure.
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

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

* Re: How to get nice with GNAT?
  2014-11-26  1:27             ` Dennis Lee Bieber
@ 2014-11-26  3:29               ` brbarkstrom
  0 siblings, 0 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-26  3:29 UTC (permalink / raw)


On Tuesday, November 25, 2014 8:27:19 PM UTC-5, Dennis Lee Bieber wrote:
> On Tue, 25 Nov 2014 13:33:01 -0500, Dennis Lee Bieber
> declaimed the following:
> 
> 
> >
> >Does leave OUT only parameters hanging, unless one just takes the view that
> >IN OUT and OUT both rely upon copying from procedure local memory to return
> >parameter memory at the same point (and an IN OUT copies from the parameter
> >memory to local memory upon entry).
> >
> 
> 	ADDENDUM: Original Ada OUT parameters were write-only from the
> viewpoint of the procedure too... Ada 95 allowed them to be used as
> read-write within the procedure.
> -- 
> 	Wulfraed                 Dennis Lee Bieber         AF6VN

The last several posts look at exception handling from several different
philosophical points of view.  It might be interesting to try to see
what these different points of view suggest with respect to
1) detection of exceptions during the initial debugging phases of development,
2) "routine" handling of exceptions during operations, for example which
   exceptions should be logged, which should we allow users to correct (bad
   input), and which are serious enough to make us want to shut down the whole
   system,
3) leaving clues about assumptions on exception handling that might reduce
   maintenance costs when a system needs revision in the future.

It sounds like there's enough divergence of opinion that collecting these
differences and creating some suggestions of practical use to programmers 
might have some value - Ada Gems or a paper at HILT or Ada-Europe might be 
interesting.  Maybe we could start by collecting material for a history
of exception handling, see if we could get some practical and quotable
quantitative experience (like how many debugging person-hours could appropriate
exception handling save), and suggestions about how to feed this experience
into Ada revisions.

Bruce B.


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

* Re: How to get nice with GNAT?
  2014-11-25 23:30               ` Simon Wright
  2014-11-26  1:25                 ` G.B.
@ 2014-11-26  6:18                 ` J-P. Rosen
  2014-11-26  7:37                   ` Simon Wright
  1 sibling, 1 reply; 59+ messages in thread
From: J-P. Rosen @ 2014-11-26  6:18 UTC (permalink / raw)


Le 26/11/2014 00:30, Simon Wright a écrit :
> We discovered that some misguided people had used
> 
>    exception
>       when others => null;
>    end;
> 
> and I had the fun of using ASIS to check the whole application for this
> pattern via ASIS2XML and an xslt-based report.
> 
> Today I expect we'd use AdaControl. I have to say I don't remember
> whether we could have then (probably about 2007).

You could ;-). The rule to check this (statements
(exception_others_null)) has been introduced in version 1.5r16, october
2006.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


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

* Re: How to get nice with GNAT?
  2014-11-26  1:25                 ` G.B.
@ 2014-11-26  7:35                   ` Simon Wright
  2014-11-26 11:55                     ` Georg Bauhaus
  0 siblings, 1 reply; 59+ messages in thread
From: Simon Wright @ 2014-11-26  7:35 UTC (permalink / raw)


G.B. <nonlegitur@futureapps.invalid> writes:

> Simon Wright <simon@pushface.org> wrote:
> .
>> 
>> We discovered that some misguided people had used
>> 
>>    exception
>>       when others => null;
>>    end;
>
> The guidance that code like a silencing exception handler can be
> following may be orienting towards presentational flawlessness
> (polish). When demonstrating a program, the audience can include
> hounds. Then either the program must appear to them to be without
> flaw, which in case of exceptions on the screen it isn't. Or, the
> presenter must be capable of silencing rhetoric.  Otherwise, the
> hounds will snap and the presenter is going to be a toy.

Not an argument that applies to point-defence missile systems!

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

* Re: How to get nice with GNAT?
  2014-11-26  6:18                 ` J-P. Rosen
@ 2014-11-26  7:37                   ` Simon Wright
  0 siblings, 0 replies; 59+ messages in thread
From: Simon Wright @ 2014-11-26  7:37 UTC (permalink / raw)


"J-P. Rosen" <rosen@adalog.fr> writes:

> Le 26/11/2014 00:30, Simon Wright a écrit :
>> We discovered that some misguided people had used
>> 
>>    exception
>>       when others => null;
>>    end;
>> 
>> and I had the fun of using ASIS to check the whole application for this
>> pattern via ASIS2XML and an xslt-based report.
>> 
>> Today I expect we'd use AdaControl. I have to say I don't remember
>> whether we could have then (probably about 2007).
>
> You could ;-). The rule to check this (statements
> (exception_others_null)) has been introduced in version 1.5r16, october
> 2006.

Apologies, then

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

* Re: How to get nice with GNAT?
  2014-11-25 22:12             ` Randy Brukardt
  2014-11-25 23:30               ` Simon Wright
@ 2014-11-26  8:41               ` Dmitry A. Kazakov
  1 sibling, 0 replies; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-26  8:41 UTC (permalink / raw)


On Tue, 25 Nov 2014 16:12:07 -0600, Randy Brukardt wrote:

> Exceptions surely aren't enough to prevent all security issues, but they can 
> help avoid a substantial number of them.

Exceptions is a tool to improve design:

1. Cleaner interfaces
2. Cleaner code
3. Less coupling between the provided and the client
4. Better performance

Fewer security issues is a consequence of a better design.
 
> (As previously noted, if you could prove that no exceptions are possible - 
> meaning that no low-level bugs are possible - that would be better than 
> having to figure out last-chance handlers and the like, but that's still 
> beyond the state of the art for general purpose code. When that changes, 
> I'll reconsider my stance on exceptions, but not until then.)

I would add that usual rants about unhandled exceptions is rubbish. Because
other methods of indicating an alternative execution state require handling
no less. Errors of not handling such states are *less* visible without
using exceptions than with exceptions.

------------------
* With exception of exceptions (:-)) introduced without need, e.g. like in
the notorious accessibility checks.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: How to get nice with GNAT?
  2014-11-26  7:35                   ` Simon Wright
@ 2014-11-26 11:55                     ` Georg Bauhaus
  2014-11-26 13:06                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 59+ messages in thread
From: Georg Bauhaus @ 2014-11-26 11:55 UTC (permalink / raw)


On 26.11.14 08:35, Simon Wright wrote:
> Not an argument that applies to point-defence missile systems!

That's good to know. I take it to mean that exceptions will less
frequently have this tendency to backfire, an effect that checking
return values in C can so easily produce:

    extern int foo(...);


    if (foo(...) < 0) {
       /* do something assuming that negative return values
          are error codes. */


And forgot overflow + wrap around.  Ouch!

This is another argument against

   when others =>

in Ada programs, too, unless there is a very good reason to include
a catch-all.

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

* Re: How to get nice with GNAT?
  2014-11-26 11:55                     ` Georg Bauhaus
@ 2014-11-26 13:06                       ` Dmitry A. Kazakov
  2014-11-26 13:36                         ` brbarkstrom
  2014-11-26 21:27                         ` Randy Brukardt
  0 siblings, 2 replies; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-26 13:06 UTC (permalink / raw)


On Wed, 26 Nov 2014 12:55:39 +0100, Georg Bauhaus wrote:

> On 26.11.14 08:35, Simon Wright wrote:
>> Not an argument that applies to point-defence missile systems!
> 
> That's good to know. I take it to mean that exceptions will less
> frequently have this tendency to backfire, an effect that checking
> return values in C can so easily produce:
> 
>     extern int foo(...);
> 
> 
>     if (foo(...) < 0) {
>        /* do something assuming that negative return values
>           are error codes. */
> 
> 
> And forgot overflow + wrap around.  Ouch!
> 
> This is another argument against
> 
>    when others =>
> 
> in Ada programs, too, unless there is a very good reason to include
> a catch-all.

If exceptions were under a contract, the list of possible exceptions to
catch would be definite and quite small in most cases. So, actually, we
could disallow "when others" for all subprograms having an exception
contract and calling only such subprograms (statically).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: How to get nice with GNAT?
  2014-11-26 13:06                       ` Dmitry A. Kazakov
@ 2014-11-26 13:36                         ` brbarkstrom
  2014-11-26 21:27                         ` Randy Brukardt
  1 sibling, 0 replies; 59+ messages in thread
From: brbarkstrom @ 2014-11-26 13:36 UTC (permalink / raw)


On Wednesday, November 26, 2014 8:06:28 AM UTC-5, Dmitry A. Kazakov wrote:
> On Wed, 26 Nov 2014 12:55:39 +0100, Georg Bauhaus wrote:
> 
> > On 26.11.14 08:35, Simon Wright wrote:
> >> Not an argument that applies to point-defence missile systems!
> > 
> > That's good to know. I take it to mean that exceptions will less
> > frequently have this tendency to backfire, an effect that checking
> > return values in C can so easily produce:
> > 
> >     extern int foo(...);
> > 
> > 
> >     if (foo(...) < 0) {
> >        /* do something assuming that negative return values
> >           are error codes. */
> > 
> > 
> > And forgot overflow + wrap around.  Ouch!
> > 
> > This is another argument against
> > 
> >    when others =>
> > 
> > in Ada programs, too, unless there is a very good reason to include
> > a catch-all.
> 
> If exceptions were under a contract, the list of possible exceptions to
> catch would be definite and quite small in most cases. So, actually, we
> could disallow "when others" for all subprograms having an exception
> contract and calling only such subprograms (statically).
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

The idea of creating an "exception contract" sounds useful.  In a bit more
formal setting, the list of specific exceptions might become part of a design
audit procedure.  It would show what kinds of exceptional conditions the 
designers and and coders had considered.  when others => should probably
be treated as a bad design unless the handler re-raises the exception before
finishing.

Bruce B.
coders 


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

* Re: How to get nice with GNAT?
  2014-11-26 13:06                       ` Dmitry A. Kazakov
  2014-11-26 13:36                         ` brbarkstrom
@ 2014-11-26 21:27                         ` Randy Brukardt
  2014-11-26 22:38                           ` brbarkstrom
  2014-11-27  8:52                           ` Dmitry A. Kazakov
  1 sibling, 2 replies; 59+ messages in thread
From: Randy Brukardt @ 2014-11-26 21:27 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:g70ue0kjz9qi$.1b2fj6sqtjbez$.dlg@40tude.net...
...
> If exceptions were under a contract, the list of possible exceptions to
> catch would be definite and quite small in most cases. So, actually, we
> could disallow "when others" for all subprograms having an exception
> contract and calling only such subprograms (statically).

The practical problem with exception contracts is that they encourage people 
(especially coders rather than engineers) to "eat" exceptions rather than to 
figure out what ought to be done with them (or better yet, redoing the 
code/preconditions/predicates so they can't arise). That's the practical 
experience with them in Java, and that has caused some ARG members to be 
rather strongly against them. (Which is why they didn't make it into Ada 
2012.)

I personally find that misguided (because Ada is for engineers, not coders), 
and I'll try again with them the next Ada amendment.

BTW, that's a problem with all statically cateogorization contracts. We're 
looking at a potentially blocking cateogorization as part of the 
parallelization effort. What happens there is that calling any routine that 
is potentially blocking is illegal inside of a routine that is declared as 
non-blocking. (And unlike exception contracts, there's no workaround). The 
effect is that one has to change the status of lots of routines in order to 
use the categorization. (At least for this particular categorization, Ada 
already says which language-defined routines are potentially blocking, so 
it's just a matter of putting that into aspects and pragmas as needed - no 
arguments about whether Sin should be potentially blocking :-)

Even so, I think statically checked contracts and categorizations are going 
to be important, because they eliminate bugs at the source (and thus 
eliminate the need to worry about how to handle a substantial proportion of 
errors).

                                       Randy.



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

* Re: How to get nice with GNAT?
  2014-11-26 21:27                         ` Randy Brukardt
@ 2014-11-26 22:38                           ` brbarkstrom
  2014-11-27  9:01                             ` Dmitry A. Kazakov
  2014-11-27  8:52                           ` Dmitry A. Kazakov
  1 sibling, 1 reply; 59+ messages in thread
From: brbarkstrom @ 2014-11-26 22:38 UTC (permalink / raw)


On Wednesday, November 26, 2014 4:27:37 PM UTC-5, Randy Brukardt wrote:
> "Dmitry A. Kazakov"  wrote in s message 
> 
> ...
> > If exceptions were under a contract, the list of possible exceptions to
> > catch would be definite and quite small in most cases. So, actually, we
> > could disallow "when others" for all subprograms having an exception
> > contract and calling only such subprograms (statically).
> 
> The practical problem with exception contracts is that they encourage people 
> (especially coders rather than engineers) to "eat" exceptions rather than to 
> figure out what ought to be done with them (or better yet, redoing the 
> code/preconditions/predicates so they can't arise). That's the practical 
> experience with them in Java, and that has caused some ARG members to be 
> rather strongly against them. (Which is why they didn't make it into Ada 
> 2012.)
> 
> I personally find that misguided (because Ada is for engineers, not coders), 
> and I'll try again with them the next Ada amendment.
> 
> BTW, that's a problem with all statically cateogorization contracts. We're 
> looking at a potentially blocking cateogorization as part of the 
> parallelization effort. What happens there is that calling any routine that 
> is potentially blocking is illegal inside of a routine that is declared as 
> non-blocking. (And unlike exception contracts, there's no workaround). The 
> effect is that one has to change the status of lots of routines in order to 
> use the categorization. (At least for this particular categorization, Ada 
> already says which language-defined routines are potentially blocking, so 
> it's just a matter of putting that into aspects and pragmas as needed - no 
> arguments about whether Sin should be potentially blocking :-)
> 
> Even so, I think statically checked contracts and categorizations are going 
> to be important, because they eliminate bugs at the source (and thus 
> eliminate the need to worry about how to handle a substantial proportion of 
> errors).
> 
>                                        Randy.

I think it may be sensible to think of exceptions as contingent events
that we couldn't include in the original design because
a) we aren't omniscient
[as a subset of that] a1) we're building complex mechanisms that have
unexpected interactions between the parts
b) the environment in which the program operates changes in unpredictable
ways
As a result, we are nearly certain to discover unexpected events only after
we put the system into operation.

Maybe a sensible idea would be to see if we could agree on a ranking with
a small number of categories and try to suggest appropriate exception 
handling policies and strategies for each category.  For example,
a) nuisances: unexepcted events that have minor impact, such as user
input that has a mixed case character string when we really wanted all
upper case.  Maybe if a procedure detects this condition, it could change
all the lower case characters to upper case as part of the exception handling
without re-raising the exception.
b) unpleasantries: unexpected events that have some impact, but don't
warrant a system panic.  As an example, perhaps one user in a multi-user
Web site sends in a string that would overflow a buffer.  This could be
a malicious attack, which is serious, but if caught, the exception handler
could deep six the response after logging the string and the source.
c) emergencies: unexpected events that have major impact including system
failure.  These are probably the hardest to plan for.  I remember that we
had two instances of failure due to operator errors in bringing up one of
those large UPS's.  The failures were a year apart and the personnel were
the same.

I'll note that the exceptions already built into Ada fall into big
categories that are similar in intent to this suggestion.  What might
be useful is to extend the approach to smaller categories and then use
a list of these as a basis for design and procedural audits of systems.
Such a list could also be helpful as a "standardization" of the jobs
system maintainers might have to deal with.

I suppose the best one can do immediately after an  uncertainty causes
a serious exception is triage on the initial problem.  The language cannot 
be expected to handle all the ingenious idiocy of us humans.  Building a 
culture of careful design and rewarding thoughtful responses that reduce 
problems is probably the most sensible response - but it's hard.  Maybe
we need an organization like the National Transportation Safety Board
that has publicly accessible accident reports.  Alternatively, maybe there's
a role for system underwriters that could provide independent assessments
of the cost of dealing with various system failures. 

Bruce B.


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

* Re: How to get nice with GNAT?
  2014-11-26 21:27                         ` Randy Brukardt
  2014-11-26 22:38                           ` brbarkstrom
@ 2014-11-27  8:52                           ` Dmitry A. Kazakov
  1 sibling, 0 replies; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-27  8:52 UTC (permalink / raw)


On Wed, 26 Nov 2014 15:27:35 -0600, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:g70ue0kjz9qi$.1b2fj6sqtjbez$.dlg@40tude.net...
> ...
>> If exceptions were under a contract, the list of possible exceptions to
>> catch would be definite and quite small in most cases. So, actually, we
>> could disallow "when others" for all subprograms having an exception
>> contract and calling only such subprograms (statically).
> 
> The practical problem with exception contracts is that they encourage people 
> (especially coders rather than engineers) to "eat" exceptions rather than to 
> figure out what ought to be done with them (or better yet, redoing the 
> code/preconditions/predicates so they can't arise). That's the practical 
> experience with them in Java, and that has caused some ARG members to be 
> rather strongly against them. (Which is why they didn't make it into Ada 
> 2012.)

Right, but only if you require all subprograms to have contracts. Why
should we? We couldn't anyway because it would break backward
compatibility. Thus, IMO, there is nothing to worry about here.

> I personally find that misguided (because Ada is for engineers, not coders), 
> and I'll try again with them the next Ada amendment.

Good

> BTW, that's a problem with all statically cateogorization contracts. We're 
> looking at a potentially blocking cateogorization as part of the 
> parallelization effort. What happens there is that calling any routine that 
> is potentially blocking is illegal inside of a routine that is declared as 
> non-blocking. (And unlike exception contracts, there's no workaround). The 
> effect is that one has to change the status of lots of routines in order to 
> use the categorization.

Which is desired, isn't it?

> (At least for this particular categorization, Ada 
> already says which language-defined routines are potentially blocking, so 
> it's just a matter of putting that into aspects and pragmas as needed - no 
> arguments about whether Sin should be potentially blocking :-)

Conditionally blocking? Some predicates could depend (statically) on
expressions. This is important for exceptions as well:

   generic
      with procedure Visitor (E : Element);
   procedure Iterate (X : Container);
 
If Visitor is not contracted and Iterate is, then the contract of Iterate
should be "I raise, what Visitor does".

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: How to get nice with GNAT?
  2014-11-26 22:38                           ` brbarkstrom
@ 2014-11-27  9:01                             ` Dmitry A. Kazakov
  2014-11-27 13:53                               ` brbarkstrom
  0 siblings, 1 reply; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-27  9:01 UTC (permalink / raw)


On Wed, 26 Nov 2014 14:38:29 -0800 (PST), brbarkstrom@gmail.com wrote:

> I think it may be sensible to think of exceptions as contingent events
> that we couldn't include in the original design because
> a) we aren't omniscient
> [as a subset of that] a1) we're building complex mechanisms that have
> unexpected interactions between the parts

?

> b) the environment in which the program operates changes in unpredictable
> ways
> As a result, we are nearly certain to discover unexpected events only after
> we put the system into operation.

No. Exceptions are *expected* events (system states), always.

An unexpected event is when a nuke falls down on the system box. Bugs are
unexpected events.

Exception propagation is not a bug. It is a valid and anticipated system
state. Compare it with 2x3 computed as 5 because addition was used instead
of multiplication. This is also a bug, but there is nothing vicious in
addition per se.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: How to get nice with GNAT?
  2014-11-27  9:01                             ` Dmitry A. Kazakov
@ 2014-11-27 13:53                               ` brbarkstrom
  2014-11-27 17:19                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 59+ messages in thread
From: brbarkstrom @ 2014-11-27 13:53 UTC (permalink / raw)


On Thursday, November 27, 2014 4:01:19 AM UTC-5, Dmitry A. Kazakov wrote:
> On Wed, 26 Nov 2014 14:38:29 -0800 (PST), brbarkstrom wrote:
> 
> > I think it may be sensible to think of exceptions as contingent events
> > that we couldn't include in the original design because
> > a) we aren't omniscient
> > [as a subset of that] a1) we're building complex mechanisms that have
> > unexpected interactions between the parts
> 
> ?
> 
> > b) the environment in which the program operates changes in unpredictable
> > ways
> > As a result, we are nearly certain to discover unexpected events only after
> > we put the system into operation.
> 
> No. Exceptions are *expected* events (system states), always.
> 
> An unexpected event is when a nuke falls down on the system box. Bugs are
> unexpected events.
> 
> Exception propagation is not a bug. It is a valid and anticipated system
> state. Compare it with 2x3 computed as 5 because addition was used instead
> of multiplication. This is also a bug, but there is nothing vicious in
> addition per se.
> 
> -- 
> Regards,
> Dmitry A. Kazakov


Sure, but often enough we add in exceptions after having to respond to an 
unexpected event.  The addition of the exception comes in maintenance, rather 
than as result of the design work.  Of course, sometimes we've had enough 
experience with previous errors to put the exception in as part of the design.

Thanks for the clarification.

Bruce B.

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

* Re: How to get nice with GNAT?
  2014-11-27 13:53                               ` brbarkstrom
@ 2014-11-27 17:19                                 ` Dmitry A. Kazakov
  2014-12-01 22:25                                   ` Randy Brukardt
  0 siblings, 1 reply; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-27 17:19 UTC (permalink / raw)


On Thu, 27 Nov 2014 05:53:27 -0800 (PST), brbarkstrom@gmail.com wrote:

> Sure, but often enough we add in exceptions after having to respond to an 
> unexpected event.

And this still is a BUG.

An unexpected even means that the system is in an undefined state, there is
nothing you could do with this. All other cases, even when the system
(subsystem actually) gets shut down, restarted etc are actions in response
to some *expected* event. E.g. even memory access violation is an event
expected by the OS process scheduler or debugger etc.

> The addition of the exception comes in maintenance, rather 
> than as result of the design work.

Yes, but that is when the state is expected but undesired. It is not a bug
at the side which raised the exception. It could be a bug on the client's
side, e.g. due to improper usage.

What is usually meant by exceptions being bugs is that the code raises an
exception where some other behavior specified. That is indeed a bug, but it
is not specific to exceptions, like with the example of + used instead of
*. Any wrong behavior is a bug.

The idea that all/most/some bugs should somehow manifest their wrong
behavior in exceptions is dubious.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: How to get nice with GNAT?
  2014-11-27 17:19                                 ` Dmitry A. Kazakov
@ 2014-12-01 22:25                                   ` Randy Brukardt
  2014-12-02  8:42                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 59+ messages in thread
From: Randy Brukardt @ 2014-12-01 22:25 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1g5ttpzi8eywc$.1gluj9evlmeus.dlg@40tude.net...
...
> The idea that all/most/some bugs should somehow manifest their wrong
> behavior in exceptions is dubious.

Fascinating. I'd say the reverse: that almost all bugs quickly manifest 
themselves in an exception (at least in well-designed Ada code). For 
instance, I tend to make off-by-one errors in index calculations. Such 
errors almost always result in a Constraint_Error when the index is used. 
Similarly, in Janus/Ada, we've sometimes passed the wrong entity to a 
subprogram; that almost always shows up as a Constraint_Error detecting the 
use of a non-existent variant. (If a routine expects a symboltable pointer 
to an object, and gets a package, the components it needs aren't going to be 
there.)

Indeed, the recent history of Ada includes more and more ways to specify 
what is expected/needed for a parameter/object/component. Null exclusions 
(Ada 2005), preconditions, and predicates (Ada 2012) are all ways to more 
closely tell the compiler what is intended.

The next step, IMHO, is to include exception contracts that effectively 
require exceptions not to occur. If they in fact do occur, then the program 
is wrong and will be rejected by the compiler. That means that "unexpected" 
Constraint_Errors will be detected statically and thus the manifestation of 
many bugs can be detected -- thus eliminating the bugs at the source.

Of course, once that next step is taken (and I mean in the context of the 
full Ada language, not just some simple subset like SPARK), then you'll 
probably be right. But that's still some distance in the future.

                                                              Randy.


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

* Re: How to get nice with GNAT?
  2014-12-01 22:25                                   ` Randy Brukardt
@ 2014-12-02  8:42                                     ` Dmitry A. Kazakov
  2014-12-03 21:41                                       ` Randy Brukardt
  0 siblings, 1 reply; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-12-02  8:42 UTC (permalink / raw)


On Mon, 1 Dec 2014 16:25:28 -0600, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1g5ttpzi8eywc$.1gluj9evlmeus.dlg@40tude.net...
> ...
>> The idea that all/most/some bugs should somehow manifest their wrong
>> behavior in exceptions is dubious.
> 
> Fascinating. I'd say the reverse: that almost all bugs quickly manifest 
> themselves in an exception (at least in well-designed Ada code). For 
> instance, I tend to make off-by-one errors in index calculations. Such 
> errors almost always result in a Constraint_Error when the index is used. 

The index may slip toward another side. Why do you expect that any wrong
index would always be out of the range?

> Similarly, in Janus/Ada, we've sometimes passed the wrong entity to a 
> subprogram; that almost always shows up as a Constraint_Error detecting the 
> use of a non-existent variant. (If a routine expects a symboltable pointer 
> to an object, and gets a package, the components it needs aren't going to be 
> there.)

In such cases I just use tagged types. The problem here is in weakly-typed
design, which makes run-time type errors possible.

> Indeed, the recent history of Ada includes more and more ways to specify 
> what is expected/needed for a parameter/object/component. Null exclusions 
> (Ada 2005), preconditions, and predicates (Ada 2012) are all ways to more 
> closely tell the compiler what is intended.
> 
> The next step, IMHO, is to include exception contracts that effectively 
> require exceptions not to occur. If they in fact do occur, then the program 
> is wrong and will be rejected by the compiler. That means that "unexpected" 
> Constraint_Errors will be detected statically and thus the manifestation of 
> many bugs can be detected -- thus eliminating the bugs at the source.
>
> Of course, once that next step is taken (and I mean in the context of the 
> full Ada language, not just some simple subset like SPARK), then you'll 
> probably be right. But that's still some distance in the future.

No. Statically eliminated bugs don't manifest themselves at all. They make
the program illegal.

The point is that bugs in a legal program may expose any behavior [within
of possible]. There is no way to predict this behavior and thus hoping that
it would become an exception or setting some variable in some way is
dubious.

SPARK or any language design would not change this, the bugs they catch are
caught, which is good, but the rest will act as it always does.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: How to get nice with GNAT?
  2014-12-02  8:42                                     ` Dmitry A. Kazakov
@ 2014-12-03 21:41                                       ` Randy Brukardt
  2014-12-06 12:02                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 59+ messages in thread
From: Randy Brukardt @ 2014-12-03 21:41 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:hz0z7hi7czmw$.1qfhyt5f4awot.dlg@40tude.net...
> On Mon, 1 Dec 2014 16:25:28 -0600, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1g5ttpzi8eywc$.1gluj9evlmeus.dlg@40tude.net...
>> ...
>>> The idea that all/most/some bugs should somehow manifest their wrong
>>> behavior in exceptions is dubious.
>>
>> Fascinating. I'd say the reverse: that almost all bugs quickly manifest
>> themselves in an exception (at least in well-designed Ada code). For
>> instance, I tend to make off-by-one errors in index calculations. Such
>> errors almost always result in a Constraint_Error when the index is used.
>
> The index may slip toward another side. Why do you expect that any wrong
> index would always be out of the range?

"Any wrong index"? I never said that. At some point, the off-by-one error 
will be out of the expected range and a Constraint_Error will result. And 
that will directly show the problem.

>> Similarly, in Janus/Ada, we've sometimes passed the wrong entity to a
>> subprogram; that almost always shows up as a Constraint_Error detecting 
>> the
>> use of a non-existent variant. (If a routine expects a symboltable 
>> pointer
>> to an object, and gets a package, the components it needs aren't going to 
>> be
>> there.)
>
> In such cases I just use tagged types. The problem here is in weakly-typed
> design, which makes run-time type errors possible.

Huh? The thing passed is an access-to-a-symbol, which is an 
access-to-variant-record in an untagged design, or an 
access-to-class-wide-symbol in a tagged design. Either way, you'll get a 
run-time error. In Ada 2012, you could use a predicate on the parameter in 
order to make the check sooner, but it still will be a runtime check.

I should note that most of my compiler work was with the code that converts 
semantic information into intermediate code. That means I'm taking an 
expression tree (with "Name" nodes decorated with symbol pointers) and 
converting it to a form closer to machine code. These can't be primitive 
operations of the symbol type (it might have been possible to make them 
primitive operations of the expression tree nodes, but that's irrelevant to 
this point), so the only realistic possibility is going to be 
access-to-something with associated runtime checks.

In may experience, most problems come down to managing combinations of 
several kinds of objects (in the abstract sense, not the Ada sense), and 
it's not sensible to try to do that in any sort of statically typed manner. 
(Especially in Ada, where only one inheritance tree can be primitive, but 
it's also true in general, because there are too many combinations to deal 
with.) Strong typing is great to eliminate gross errors (like passing an 
expression node when a symbol entry was meant -- as both are represented as 
access types, they can easily be confused), but it's not going to catch the 
lower-level mistakes.

>> Indeed, the recent history of Ada includes more and more ways to specify
>> what is expected/needed for a parameter/object/component. Null exclusions
>> (Ada 2005), preconditions, and predicates (Ada 2012) are all ways to more
>> closely tell the compiler what is intended.
>>
>> The next step, IMHO, is to include exception contracts that effectively
>> require exceptions not to occur. If they in fact do occur, then the 
>> program
>> is wrong and will be rejected by the compiler. That means that 
>> "unexpected"
>> Constraint_Errors will be detected statically and thus the manifestation 
>> of
>> many bugs can be detected -- thus eliminating the bugs at the source.
>>
>> Of course, once that next step is taken (and I mean in the context of the
>> full Ada language, not just some simple subset like SPARK), then you'll
>> probably be right. But that's still some distance in the future.
>
> No. Statically eliminated bugs don't manifest themselves at all. They make
> the program illegal.

Exactly. Which means that they never get to runtime at all -- which is the 
ultimate goal for making programs more correct.

> The point is that bugs in a legal program may expose any behavior [within
> of possible]. There is no way to predict this behavior and thus hoping 
> that
> it would become an exception or setting some variable in some way is
> dubious.
>
> SPARK or any language design would not change this, the bugs they catch 
> are
> caught, which is good, but the rest will act as it always does.

Of course, no technology could ever catch every bug. But the point here is 
to reduce the universe of legal possibilities, hopefully to the limit so 
that either an exception is raised or the program works as designed. Note 
that the latter still could in fact be buggy, because a lot of programs work 
as designed but still don't do what they are supposed to do (at the human 
level). No technology could ever eliminate that case, as such it's not worth 
even talking about other than to acknowledge its existence.

                                                             Randy.



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

* Re: How to get nice with GNAT?
  2014-12-03 21:41                                       ` Randy Brukardt
@ 2014-12-06 12:02                                         ` Dmitry A. Kazakov
  2014-12-08 22:45                                           ` Randy Brukardt
  0 siblings, 1 reply; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-12-06 12:02 UTC (permalink / raw)


On Wed, 3 Dec 2014 15:41:12 -0600, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:hz0z7hi7czmw$.1qfhyt5f4awot.dlg@40tude.net...
>> On Mon, 1 Dec 2014 16:25:28 -0600, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:1g5ttpzi8eywc$.1gluj9evlmeus.dlg@40tude.net...
>>> ...
>>>> The idea that all/most/some bugs should somehow manifest their wrong
>>>> behavior in exceptions is dubious.
>>>
>>> Fascinating. I'd say the reverse: that almost all bugs quickly manifest
>>> themselves in an exception (at least in well-designed Ada code). For
>>> instance, I tend to make off-by-one errors in index calculations. Such
>>> errors almost always result in a Constraint_Error when the index is used.
>>
>> The index may slip toward another side. Why do you expect that any wrong
>> index would always be out of the range?
> 
> "Any wrong index"? I never said that. At some point, the off-by-one error 
> will be out of the expected range and a Constraint_Error will result.

Which is a very specific kind of all bugs which may happen with index
calculation, a quite infrequent one in Ada.

> And that will directly show the problem.

Ada has quite good means to ensure this never to happen. In my practice I
can remember only one or two cases I got "subscript error". I believe the
possibility of such bug could be significantly reduced if Ada's renaming
were fixed, e.g. if you could slide indices per renaming and have other
safe means to "translate" indices of one array into indices of another.

>>> Similarly, in Janus/Ada, we've sometimes passed the wrong entity to a
>>> subprogram; that almost always shows up as a Constraint_Error detecting 
>>> the use of a non-existent variant. (If a routine expects a symboltable 
>>> pointer to an object, and gets a package, the components it needs aren't going to 
>>> be there.)
>>
>> In such cases I just use tagged types. The problem here is in weakly-typed
>> design, which makes run-time type errors possible.
> 
> Huh? The thing passed is an access-to-a-symbol, which is an 
> access-to-variant-record in an untagged design, or an 
> access-to-class-wide-symbol in a tagged design.

The subprogram you pass it should have been a primitive operation.

> Either way, you'll get a run-time error.

Yes, because it is weakly-typed. I would even dare put up a definition:

   Typing is weak when type errors are run-time errors

   (Untyped is when type errors are run-time bugs)

> In Ada 2012, you could use a predicate on the parameter in 
> order to make the check sooner, but it still will be a runtime check.

And this still be weakly-typed, which is why dynamic predicates are so
dangerous. They add nothing but another possibility for having a bug.
 
> In may experience, most problems come down to managing combinations of 
> several kinds of objects (in the abstract sense, not the Ada sense), and 
> it's not sensible to try to do that in any sort of statically typed manner.

Which is using Ada as if it were C. The combinations of objects should be
handled in a way allowing to map combinations onto the language items
allowing static checks. Yes, it is not always possible, and where not
possible it becomes a C program in Ada, partially of course.

> (Especially in Ada, where only one inheritance tree can be primitive, but 
> it's also true in general, because there are too many combinations to deal 
> with.)

Which is why MI and MD are needed so badly.

> Strong typing is great to eliminate gross errors (like passing an 
> expression node when a symbol entry was meant -- as both are represented as 
> access types, they can easily be confused), but it's not going to catch the 
> lower-level mistakes.

This is true because typing cannot express all the semantics and thus some
semantic errors will slip through. But that does not justify not using
typing where possible.

>> The point is that bugs in a legal program may expose any behavior [within
>> of possible]. There is no way to predict this behavior and thus hoping that
>> it would become an exception or setting some variable in some way is dubious.
>>
>> SPARK or any language design would not change this, the bugs they catch 
>> are caught, which is good, but the rest will act as it always does.
> 
> Of course, no technology could ever catch every bug. But the point here is 
> to reduce the universe of legal possibilities, hopefully to the limit so 
> that either an exception is raised or the program works as designed. Note 
> that the latter still could in fact be buggy, because a lot of programs work 
> as designed but still don't do what they are supposed to do (at the human 
> level). No technology could ever eliminate that case, as such it's not worth 
> even talking about other than to acknowledge its existence.

Yes.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: How to get nice with GNAT?
  2014-12-06 12:02                                         ` Dmitry A. Kazakov
@ 2014-12-08 22:45                                           ` Randy Brukardt
  2014-12-09  8:51                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 59+ messages in thread
From: Randy Brukardt @ 2014-12-08 22:45 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1adpj5cs8xtkf$.hqv9tsofbfgz$.dlg@40tude.net...
> On Wed, 3 Dec 2014 15:41:12 -0600, Randy Brukardt wrote:
...
>> Huh? The thing passed is an access-to-a-symbol, which is an
>> access-to-variant-record in an untagged design, or an
>> access-to-class-wide-symbol in a tagged design.
>
> The subprogram you pass it should have been a primitive operation.

Not practical. I explained why later.

>> Either way, you'll get a run-time error.
>
> Yes, because it is weakly-typed. I would even dare put up a definition:
>
>   Typing is weak when type errors are run-time errors
>
>   (Untyped is when type errors are run-time bugs)

By this definition (which is not the typical definition of the phrase), any 
realistic program is weakly-typed.

>> In Ada 2012, you could use a predicate on the parameter in
>> order to make the check sooner, but it still will be a runtime check.
>
> And this still be weakly-typed, which is why dynamic predicates are so
> dangerous. They add nothing but another possibility for having a bug.
>
>> In may experience, most problems come down to managing combinations of
>> several kinds of objects (in the abstract sense, not the Ada sense), and
>> it's not sensible to try to do that in any sort of statically typed 
>> manner.
>
> Which is using Ada as if it were C. The combinations of objects should be
> handled in a way allowing to map combinations onto the language items
> allowing static checks. Yes, it is not always possible, and where not
> possible it becomes a C program in Ada, partially of course.

Not at all. C has no run-time checks; you'll never get any sort of error 
from it unless you write it explicitly yourself. I'm never going to have 
enough fortitude to write thousands of pages of checks by hand; I've got to 
have language support to make those checks.

In any case, your vision of strong typing (which is many times stronger than 
what I could stand) is completely impractical for me. I tried it in the Claw 
builder, and the result is very hard to extend. To add a new kind of window 
object, one has to write implementations for roughly 80 primitive 
subprograms; roughly 5000 lines of code. To add a new capability, one has to 
add implementations of new primitive operations to all of the existing kinds 
of window objects (around 20 at last count). Either of those takes multiple 
days of work before anything can be compiled. Since I'm "agile" to my core 
(and long before such a thing even had a name), spending more than 4 hours 
or so writing anything without a compile/run/test cycle is scary. Especially 
as I can't really remember what I did if it goes longer than that; debugging 
takes much longer if more code is involved. (In such a case, you have to 
re-remember what your plan was for particular problems -- it's much more 
like debugging existing code than something you just finished writing.)

Anyway, I think we just have to agree to disagree on this one.

My goal is to bring more static detection of what are formally run-time 
errors in Ada. I don't think calling that "typing" is helpful in any way, 
because the mechanisms are so different. YMMV.

                                              Randy.



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

* Re: How to get nice with GNAT?
  2014-12-08 22:45                                           ` Randy Brukardt
@ 2014-12-09  8:51                                             ` Dmitry A. Kazakov
  2014-12-09 23:14                                               ` Brad Moore
  0 siblings, 1 reply; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-12-09  8:51 UTC (permalink / raw)


On Mon, 8 Dec 2014 16:45:51 -0600, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1adpj5cs8xtkf$.hqv9tsofbfgz$.dlg@40tude.net...
>> On Wed, 3 Dec 2014 15:41:12 -0600, Randy Brukardt wrote:
> ...
>>> Huh? The thing passed is an access-to-a-symbol, which is an
>>> access-to-variant-record in an untagged design, or an
>>> access-to-class-wide-symbol in a tagged design.
>>
>> The subprogram you pass it should have been a primitive operation.
> 
> Not practical. I explained why later.
> 
>>> Either way, you'll get a run-time error.
>>
>> Yes, because it is weakly-typed. I would even dare put up a definition:
>>
>>   Typing is weak when type errors are run-time errors
>>
>>   (Untyped is when type errors are run-time bugs)
> 
> By this definition (which is not the typical definition of the phrase), any 
> realistic program is weakly-typed.

Possibly, it depends on many factors including willingness to make the type
system aware of types beings logically different (= non-substitutable).

Regarding custom definitions of weak typing, it is usually a lot of hand
waving without much substance.

>> Which is using Ada as if it were C. The combinations of objects should be
>> handled in a way allowing to map combinations onto the language items
>> allowing static checks. Yes, it is not always possible, and where not
>> possible it becomes a C program in Ada, partially of course.
> 
> Not at all. C has no run-time checks; you'll never get any sort of error 
> from it unless you write it explicitly yourself. I'm never going to have 
> enough fortitude to write thousands of pages of checks by hand; I've got to 
> have language support to make those checks.

Yes, but we are discussing bugs, not errors. When you say that an exception
manifests a bug, then C is as good as Ada. The same bug in C will show
itself differently, but so what.

Now, if you *anticipate* an Ada run-time check to fail, you also handle
this fault appropriately in the program and it is no more a bug, and no
more a type error.

The point is that when you do not do that it is same as you would go in C
and, hence it is C programming in Ada. And reversely, if you expect a type
error in C and add checks to verify for that (= for non-substitutability)
and then handle the result, that would constitute Ada programming in C.
(:-))

> In any case, your vision of strong typing (which is many times stronger than 
> what I could stand) is completely impractical for me. I tried it in the Claw 
> builder, and the result is very hard to extend. To add a new kind of window 
> object, one has to write implementations for roughly 80 primitive 
> subprograms; roughly 5000 lines of code. To add a new capability, one has to 
> add implementations of new primitive operations to all of the existing kinds 
> of window objects (around 20 at last count). Either of those takes multiple 
> days of work before anything can be compiled. Since I'm "agile" to my core 
> (and long before such a thing even had a name), spending more than 4 hours 
> or so writing anything without a compile/run/test cycle is scary. Especially 
> as I can't really remember what I did if it goes longer than that; debugging 
> takes much longer if more code is involved. (In such a case, you have to 
> re-remember what your plan was for particular problems -- it's much more 
> like debugging existing code than something you just finished writing.)
> 
> Anyway, I think we just have to agree to disagree on this one.

Not really disagree. I know too well how difficult is to describe complex
relationships between types in Ada. Which is why I wished Ada's type system
were improved.

> My goal is to bring more static detection of what are formally run-time 
> errors in Ada.

Sure. But note, that SPARK or similar is not a replacement to typing. It is
a completely different thing aimed at correctness of a singular program
instance. Type safety is aimed at implied correctness of a multitude of
possible programs. Both are important because the latter is much more
constrained.

> I don't think calling that "typing" is helpful in any way, 
> because the mechanisms are so different. YMMV.

Singular proofs profit greatly from an elaborated type system. What could
SPARK do for C?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: How to get nice with GNAT?
  2014-12-09 23:14                                               ` Brad Moore
@ 2014-12-09 17:59                                                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 59+ messages in thread
From: Dmitry A. Kazakov @ 2014-12-09 17:59 UTC (permalink / raw)


On Tue, 09 Dec 2014 16:14:20 -0700, Brad Moore wrote:

> On 2014-12-09 1:51 AM, Dmitry A. Kazakov wrote:
>>>> Which is using Ada as if it were C. The combinations of objects should be
>>>> handled in a way allowing to map combinations onto the language items
>>>> allowing static checks. Yes, it is not always possible, and where not
>>>> possible it becomes a C program in Ada, partially of course.
>>>
>>> Not at all. C has no run-time checks; you'll never get any sort of error
>>> from it unless you write it explicitly yourself. I'm never going to have
>>> enough fortitude to write thousands of pages of checks by hand; I've got to
>>> have language support to make those checks.
>>
>> Yes, but we are discussing bugs, not errors. When you say that an exception
>> manifests a bug, then C is as good as Ada. The same bug in C will show
>> itself differently, but so what.
> 
> The "so what" is a monumentally huge difference in my experience. Aside 
> from C not having exceptions, having an exception flag an error at the 
> site of the violation can make it much easier to notice and fix the bug.

And this is still a bug and a kind of C programming allowing such bugs to
happen.

> An unhandled exception in Ada however results in the 
> program ceasing execution,

Not really. Quite frequently wrongly propagated exceptions are handled or
converted into other exceptions (like when within Finalize). Even more
frequently they are false positives like in the case of most accessibility
checks and noise when they rather hide real problem than indicate it.

> so it is more likely that the bug will be 
> noticed earlier, possibly before deployment, which can be far less costly.

No. I don't think the difference is that big. In order to detect run-time
bugs one needs tests designed to show these bugs. If an exception is not
anticipated and thus was not targeted by a intentionally designed test
chances that sporadic runs of the application will trigger it are very low.
If the exception is anticipated, then it is easier to handle it properly or
prevent altogether than to write a test.

The real advantage of Ada over C in catching bugs early is not exceptions
but static checks, most importantly static type checks.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: How to get nice with GNAT?
  2014-12-09  8:51                                             ` Dmitry A. Kazakov
@ 2014-12-09 23:14                                               ` Brad Moore
  2014-12-09 17:59                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 59+ messages in thread
From: Brad Moore @ 2014-12-09 23:14 UTC (permalink / raw)


On 2014-12-09 1:51 AM, Dmitry A. Kazakov wrote:
>>> Which is using Ada as if it were C. The combinations of objects should be
>>> handled in a way allowing to map combinations onto the language items
>>> allowing static checks. Yes, it is not always possible, and where not
>>> possible it becomes a C program in Ada, partially of course.
>>
>> Not at all. C has no run-time checks; you'll never get any sort of error
>> from it unless you write it explicitly yourself. I'm never going to have
>> enough fortitude to write thousands of pages of checks by hand; I've got to
>> have language support to make those checks.
>
> Yes, but we are discussing bugs, not errors. When you say that an exception
> manifests a bug, then C is as good as Ada. The same bug in C will show
> itself differently, but so what.

The "so what" is a monumentally huge difference in my experience. Aside 
from C not having exceptions, having an exception flag an error at the 
site of the violation can make it much easier to notice and fix the bug.
Since it is typically not practical to write all these checks by hand in 
C, it is not uncommon that the program can continue to execute 
considerably past the bug until some undesirable behaviour is eventually 
noticed as a result of a growing snowball effect. For instance, in C you 
might end up with some strange memory corruption as a side effect of the 
original bug, which may or may not be easy to reproduce, but often can 
be extremely difficult to debug. A memory corruption problem may not 
always cause a failure, and may not be actually noticed until a system 
has been deployed. An unhandled exception in Ada however results in the 
program ceasing execution, so it is more likely that the bug will be 
noticed earlier, possibly before deployment, which can be far less costly.


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

end of thread, other threads:[~2014-12-09 23:14 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
2014-11-21 12:42 ` Björn Lundin
2014-11-21 22:55 ` Randy Brukardt
2014-11-21 23:13   ` Björn Lundin
2014-11-22  9:45   ` How to get nice traceback " Natasha Kerensikova
2014-11-22  9:57     ` Dmitry A. Kazakov
2014-11-24 22:35     ` Randy Brukardt
2014-11-22 10:11 ` How to get nice " gautier_niouzes
2014-11-22 10:40   ` Natasha Kerensikova
2014-11-22 22:44 ` brbarkstrom
2014-11-22 23:24   ` Jeffrey Carter
2014-11-23 18:06   ` Björn Lundin
2014-11-23 16:13 ` brbarkstrom
2014-11-23 16:18   ` J-P. Rosen
2014-11-23 17:02   ` Jeffrey Carter
2014-11-23 17:41 ` brbarkstrom
2014-11-23 19:22   ` Simon Wright
2014-11-23 20:49   ` Jeffrey Carter
2014-11-24  3:05     ` brbarkstrom
2014-11-24  6:25       ` Jeffrey Carter
2014-11-24 14:39         ` brbarkstrom
2014-11-24 17:42       ` Dennis Lee Bieber
2014-11-25 13:45         ` brbarkstrom
2014-11-25 15:07           ` ake.ragnar.dahlgren
2014-11-25 15:51             ` brbarkstrom
2014-11-25 16:52             ` Jeffrey Carter
2014-11-25 19:18             ` G.B.
2014-11-25 20:47               ` brbarkstrom
2014-11-25 22:12             ` Randy Brukardt
2014-11-25 23:30               ` Simon Wright
2014-11-26  1:25                 ` G.B.
2014-11-26  7:35                   ` Simon Wright
2014-11-26 11:55                     ` Georg Bauhaus
2014-11-26 13:06                       ` Dmitry A. Kazakov
2014-11-26 13:36                         ` brbarkstrom
2014-11-26 21:27                         ` Randy Brukardt
2014-11-26 22:38                           ` brbarkstrom
2014-11-27  9:01                             ` Dmitry A. Kazakov
2014-11-27 13:53                               ` brbarkstrom
2014-11-27 17:19                                 ` Dmitry A. Kazakov
2014-12-01 22:25                                   ` Randy Brukardt
2014-12-02  8:42                                     ` Dmitry A. Kazakov
2014-12-03 21:41                                       ` Randy Brukardt
2014-12-06 12:02                                         ` Dmitry A. Kazakov
2014-12-08 22:45                                           ` Randy Brukardt
2014-12-09  8:51                                             ` Dmitry A. Kazakov
2014-12-09 23:14                                               ` Brad Moore
2014-12-09 17:59                                                 ` Dmitry A. Kazakov
2014-11-27  8:52                           ` Dmitry A. Kazakov
2014-11-26  6:18                 ` J-P. Rosen
2014-11-26  7:37                   ` Simon Wright
2014-11-26  8:41               ` Dmitry A. Kazakov
2014-11-25 18:33           ` Dennis Lee Bieber
2014-11-26  1:27             ` Dennis Lee Bieber
2014-11-26  3:29               ` brbarkstrom
2014-11-23 18:55 ` brbarkstrom
2014-11-23 19:30 ` brbarkstrom
2014-11-23 22:38   ` Simon Wright
2014-11-24  2:47     ` brbarkstrom

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