* Re: small code problem
[not found] <199907090927.KAA09195@toy.william.bogus>
@ 1999-07-09 13:56 ` Gerd Stolpmann
1999-07-11 19:23 ` Markus Mottl
0 siblings, 1 reply; 8+ messages in thread
From: Gerd Stolpmann @ 1999-07-09 13:56 UTC (permalink / raw)
To: caml-list
On Fri, 09 Jul 1999, William Chesters wrote:
>Gerd Stolpmann writes:
> > It is almost always a bad idea to trap Invalid_argument,
> > Out_of_memory, Stack_overflow, and Division_by_zero, as these
> > exceptions are thought as last resort that indicates a bad system
> > state that must not happen but happened.
>
>That may be a bit misleading---it's not in any sense "dangerous" to
>continue after Invalid_argument or Division_by_zero. Whether you
>check arguments before passing them in, or whether you catch the
>exceptions that may get thrown if you don't, is a matter of what seems
>more stylish/appropriate in context. (For instance, sometimes one is
>more efficient, sometimes the other.)
Right, it is not dangerous. But I disagree that it is only a matter of
"style" not to catch these exceptions. Let me explain this a bit more
abstract.
Programming can be seen as a transformation of conditions. For example:
if Array.length Sys.argv >= 1 then do_this else do_that
You can reason about this statement, and you come to the (trivial) result that
the length of the array is >= 1 just before 'do_this' is evaluated. Because
of this, 'do_this' can be something like 'Sys.argv.(0)', and evaluation is
always successful. It is important to consider this as a kind of reasoning
which is done by the programmer and which might be errorneous (it is often not
so trivial). Of course, the interpreter checks again that the array is big
enough, but I would prefer another view: Not the array size is checked, but
what the programmer thinks about the array size. This has the advantage that
Invalid_argument is an indicator that I came to the wrong conclusions when I
wrote the program. -- In the literature this is known as "defensive
programming", it often leads to much more stable programs.
>I would worry about continuing after a Stack_overflow, but I suspect
>Out_of_memory is also pretty much safe.
Stack_overflow often indicates infinite recursions, and sometimes that
the elimination of tail recursions did not work. The stack has normally
been cleaned up after that, and it should be no problem to continue, for example
because you want to save data before exiting. Out_of_memory is more serious,
because memory continues to be tight which can lead to infinite loops. I
recommend to have at least a counter, and if this exception occurs several
times, exit the program immediately.
Gerd
--
----------------------------------------------------------------------------
Gerd Stolpmann Telefon: +49 6151 997705 (privat)
Viktoriastr. 100
64293 Darmstadt EMail: Gerd.Stolpmann@darmstadt.netsurf.de (privat)
Germany
----------------------------------------------------------------------------
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: small code problem
1999-07-09 13:56 ` small code problem Gerd Stolpmann
@ 1999-07-11 19:23 ` Markus Mottl
0 siblings, 0 replies; 8+ messages in thread
From: Markus Mottl @ 1999-07-11 19:23 UTC (permalink / raw)
To: Gerd.Stolpmann; +Cc: OCAML
> Programming can be seen as a transformation of conditions. For example:
>
> if Array.length Sys.argv >= 1 then do_this else do_that
>
> You can reason about this statement, and you come to the (trivial) result that
> the length of the array is >= 1 just before 'do_this' is evaluated. Because
> of this, 'do_this' can be something like 'Sys.argv.(0)', and evaluation is
> always successful. It is important to consider this as a kind of reasoning
> which is done by the programmer and which might be errorneous (it is often not
> so trivial). Of course, the interpreter checks again that the array is big
> enough, but I would prefer another view: Not the array size is checked, but
> what the programmer thinks about the array size. This has the advantage that
> Invalid_argument is an indicator that I came to the wrong conclusions when I
> wrote the program. -- In the literature this is known as "defensive
> programming", it often leads to much more stable programs.
I also think that checking conditions by catching exceptions leads to a
wrong style of programming: if you catch such exceptions around somewhat
bigger blocks, you might catch one which was raised in a completely
different context than you had imagined. But your program would continue
as if everything were ok, possibly leading to misbehaviour in a program
part far away from the point where the exception was raised/caught. Using
explicit checks before evaluation of "dangerous" expressions is much
safer and more transparent.
Best regards,
Markus
--
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: small code problem
@ 1999-07-08 18:23 Damien Doligez
0 siblings, 0 replies; 8+ messages in thread
From: Damien Doligez @ 1999-07-08 18:23 UTC (permalink / raw)
To: caml-list
>From: "<Brad Knotwell" <knotwell@f5.com>
>let usage = lazy (Printf.printf "Usage: %s file\n" Sys.argv.(0); exit ~-1);;
>let filename =
> try
> Sys.argv.(1)
> with Invalid_argument("Array.get") ->
> Lazy.force usage;;
> [knotwell@knotwell stock]$ ./a.out
> Usage: ./a.out file
The doc says Invalid_argument should be called, but it doesn't say
anything about the string in the exception. On my alpha with the
current development version of O'Caml, this is "Array.get" for the
byte-code interpreter (which gives the expected result), but
"out-of-bound array or string access" with the native-code compiler.
The bug with uncaught exceptions seems to be architecture-specific, so
you should tell us what kind of machine and system you have.
>As an aside, I don't particular like my use of lazy and force. Is
>there a cleaner way do the same thing?
Certainly. Just write:
let usage () = Printf.printf "Usage: %s file\n" Sys.argv.(0); exit ~-1;;
let filename =
try
Sys.argv.(1)
with Invalid_argument(_) ->
usage ();;
Better yet, use the Arg module to parse your command line...
-- Damien
^ permalink raw reply [flat|nested] 8+ messages in thread
* small code problem
@ 1999-07-02 22:30 <Brad Knotwell
1999-07-08 4:56 ` Markus Mottl
1999-07-08 22:49 ` Gerd Stolpmann
0 siblings, 2 replies; 8+ messages in thread
From: <Brad Knotwell @ 1999-07-02 22:30 UTC (permalink / raw)
To: caml-list
Hello all--
I'm having a problem with a core dump due to an uncaught exception.
The following snippet of code best illustrates the problem:
let usage = lazy (Printf.printf "Usage: %s file\n" Sys.argv.(0); exit ~-1);;
let filename =
try
Sys.argv.(1)
with Invalid_argument("Array.get") ->
Lazy.force usage;;
When I compile using the byte-code compiler, it seems to work fine.
[knotwell@knotwell stock]$ ocamlc junk.ml
[knotwell@knotwell stock]$ ./a.out
Usage: ./a.out file
[knotwell@knotwell stock]$
On the other hand, when I compile with the optimizing compiler, I
receive the following:
[knotwell@knotwell stock]$ ocamlopt junk.ml
[knotwell@knotwell stock]$ ./a.out
Segmentation fault (core dumped)
[knotwell@knotwell stock]$
When I change the code slightly:
let usage = lazy (Printf.printf "Usage: %s file\n" Sys.argv.(0); exit ~-1);;
let filename =
try
Sys.argv.(1)
with _ -> (* note the pattern matching change *)
Lazy.force usage;;
I then get correct results:
[knotwell@knotwell stock]$ ocamlopt junk.ml
[knotwell@knotwell stock]$ a.out
Usage: a.out file
[knotwell@knotwell stock]$
Why do the two compilers exhibit different behaviors with the same code?
As an aside, I don't particular like my use of lazy and force. Is
there a cleaner way do the same thing?
Thanks.
--Brad
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: small code problem
1999-07-02 22:30 <Brad Knotwell
@ 1999-07-08 4:56 ` Markus Mottl
1999-07-08 22:49 ` Gerd Stolpmann
1 sibling, 0 replies; 8+ messages in thread
From: Markus Mottl @ 1999-07-08 4:56 UTC (permalink / raw)
To: knotwell; +Cc: OCAML
> I'm having a problem with a core dump due to an uncaught exception.
> The following snippet of code best illustrates the problem:
[snip]
> Why do the two compilers exhibit different behaviors with the same code?
I'd say that this is an incompatibility bug between the byte- and native
code compiler:
Both actually throw an exception - it's just not the same!
You didn't write which version of OCaml you use. The version I use
(ocaml-2.02-2) does not produce a native code executable that crashes. It
emits an uncaught exception to stderr instead.
Try this very short file:
let main () = Sys.argv.(1)
let _ = Printexc.catch main ()
This should guarantee that any uncaught exceptions get printed to stderr
instead of producing a core dump.
Then you will see that this file compiled to byte code (ocamlc) produces
this output:
Uncaught exception: Invalid_argument("Array.get")
Whereas the native code version (ocamlopt) produces:
Uncaught exception: Invalid_argument("out-of-bound array or string access")
The interpreter would behave like the byte code version - if we didn't
have the second incompatibility that the argument vector behaves
differently as mentioned in another current thread in the mailing list.
Interesting that so far noone else has come across the incompatibility
of exceptions in this case...
> As an aside, I don't particular like my use of lazy and force. Is
> there a cleaner way do the same thing?
Yes, you only need to make "usage" a unit-function:
let usage () = Printf.printf "Usage: %s file\n" Sys.argv.(0); exit ~-1
let filename =
try Sys.argv.(1) with Invalid_argument("Array.get") -> usage ()
Best regards,
Markus Mottl
--
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: small code problem
1999-07-02 22:30 <Brad Knotwell
1999-07-08 4:56 ` Markus Mottl
@ 1999-07-08 22:49 ` Gerd Stolpmann
1999-07-09 0:27 ` <Brad Knotwell
1 sibling, 1 reply; 8+ messages in thread
From: Gerd Stolpmann @ 1999-07-08 22:49 UTC (permalink / raw)
To: knotwell, caml-list
On Sat, 03 Jul 1999, Brad Knotwell wrote:
>On the other hand, when I compile with the optimizing compiler, I
>receive the following:
>
> [knotwell@knotwell stock]$ ocamlopt junk.ml
> [knotwell@knotwell stock]$ ./a.out
> Segmentation fault (core dumped)
> [knotwell@knotwell stock]$
On an x86 architecture I get a different result:
Fatal error: uncaught exception Invalid_argument("out-of-bound array or string access")
This means that there are two problems:
- The segfault
- The different exceptions raised by the bytecode and the native compiler.
>As an aside, I don't particular like my use of lazy and force. Is
>there a cleaner way do the same thing?
let usage() = Printf.printf "Usage: %s file\n" Sys.argv.(0); exit ~-1;;
let filename =
match Sys.argv with
[| |] -> failwith "You have a silly operating system"
| [| _ |] -> usage()
| _ -> Sys.argv.(1)
This solution avoids that Invalid_argument must be caught which is better
style. It is almost always a bad idea to trap Invalid_argument,
Out_of_memory, Stack_overflow, and Division_by_zero, as these exceptions
are thought as last resort that indicates a bad system state that must
not happen but happened. It is better to design the program such that
it never runs into conditions that raise these exceptions, and if they
happen nevertheless, you missed something.
Gerd
--
----------------------------------------------------------------------------
Gerd Stolpmann Telefon: +49 6151 997705 (privat)
Viktoriastr. 100
64293 Darmstadt EMail: Gerd.Stolpmann@darmstadt.netsurf.de (privat)
Germany
----------------------------------------------------------------------------
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: small code problem
1999-07-08 22:49 ` Gerd Stolpmann
@ 1999-07-09 0:27 ` <Brad Knotwell
1999-07-09 1:37 ` Fabrice Le Fessant
0 siblings, 1 reply; 8+ messages in thread
From: <Brad Knotwell @ 1999-07-09 0:27 UTC (permalink / raw)
To: Gerd.Stolpmann; +Cc: knotwell, caml-list
Gerd Stolpmann writes:
> This solution avoids that Invalid_argument must be caught which is better
> style. It is almost always a bad idea to trap Invalid_argument,
> Out_of_memory, Stack_overflow, and Division_by_zero, as these exceptions
> are thought as last resort that indicates a bad system state that must
> not happen but happened. It is better to design the program such that
> it never runs into conditions that raise these exceptions, and if they
> happen nevertheless, you missed something.
He Gerd--
This is a serious question (not an argumentative one). How do I avoid
Invalid_argument when I'm expecting the user to enter a filename on
the command-line? Or are you just talking in general?
--Brad (who's wondering if he's missed the forest for the trees)
>
> Gerd
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~1999-07-12 18:26 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <199907090927.KAA09195@toy.william.bogus>
1999-07-09 13:56 ` small code problem Gerd Stolpmann
1999-07-11 19:23 ` Markus Mottl
1999-07-08 18:23 Damien Doligez
-- strict thread matches above, loose matches on Subject: below --
1999-07-02 22:30 <Brad Knotwell
1999-07-08 4:56 ` Markus Mottl
1999-07-08 22:49 ` Gerd Stolpmann
1999-07-09 0:27 ` <Brad Knotwell
1999-07-09 1:37 ` Fabrice Le Fessant
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox