Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

<moshez> ok, I will not marry Jo-Con-El's cow.


devel / comp.lang.c / Re: Libraries using longjmp for error handling

SubjectAuthor
* Libraries using longjmp for error handling (was: Re: More on NNTPBlue-Maned_Hawk
+* Re: Libraries using longjmp for error handling (was: Re: More on NNTPJohann 'Myrkraverk' Oskarsson
|`* Re: Libraries using longjmp for error handlingBen Bacarisse
| +* Re: Libraries using longjmp for error handlingBlue-Maned_Hawk
| |`* Re: Libraries using longjmp for error handlingScott Lurndal
| | +* Re: Libraries using longjmp for error handlingAnton Shepelev
| | |`- Re: Libraries using longjmp for error handlingScott Lurndal
| | `* Re: Libraries using longjmp for error handlingKeith Thompson
| |  `- Re: Libraries using longjmp for error handlingDavid Brown
| `* Re: Libraries using longjmp for error handlingTim Rentsch
|  `* Re: Libraries using longjmp for error handlingBen Bacarisse
|   `* Re: Libraries using longjmp for error handlingTim Rentsch
|    +* Re: Libraries using longjmp for error handlingBen Bacarisse
|    |`* Re: Libraries using longjmp for error handlingTim Rentsch
|    | `* Re: Libraries using longjmp for error handlingBen Bacarisse
|    |  `* Re: Libraries using longjmp for error handlingTim Rentsch
|    |   +- Re: Libraries using longjmp for error handlingAnton Shepelev
|    |   `* Re: Libraries using longjmp for error handlingBen Bacarisse
|    |    `* Re: Libraries using longjmp for error handlingTim Rentsch
|    |     `* Re: Libraries using longjmp for error handlingBen Bacarisse
|    |      `* Re: Libraries using longjmp for error handlingTim Rentsch
|    |       `* Re: Libraries using longjmp for error handlingBen Bacarisse
|    |        `- Re: Libraries using longjmp for error handlingTim Rentsch
|    `* Re: Libraries using longjmp for error handlingAnton Shepelev
|     `* Re: Libraries using longjmp for error handlingTim Rentsch
|      `- Re: Libraries using longjmp for error handlingAnton Shepelev
+- Re: Libraries using longjmp for error handlingBen Bacarisse
+* Re: Libraries using longjmp for error handling (was: Re: More onKaz Kylheku
|`- Re: Libraries using longjmp for error handling (was: Re: More onKaz Kylheku
+* Re: Libraries using longjmp for error handling (was: Re: More onAnton Shepelev
|`* Re: Libraries using longjmp for error handlingBen Bacarisse
| `* Re: Libraries using longjmp for error handlingAnton Shepelev
|  +* Re: Libraries using longjmp for error handlingKaz Kylheku
|  |+* Re: Libraries using longjmp for error handlingScott Lurndal
|  ||+- Re: Libraries using longjmp for error handlingKaz Kylheku
|  ||`- Re: Libraries using longjmp for error handlingBen Bacarisse
|  |`* Re: Libraries using longjmp for error handlingTim Rentsch
|  | +* Re: Libraries using longjmp for error handlingKaz Kylheku
|  | |`- Re: Libraries using longjmp for error handlingTim Rentsch
|  | `* Re: Libraries using longjmp for error handlingKeith Thompson
|  |  +* Re: Libraries using longjmp for error handlingBen Bacarisse
|  |  |`- Re: Libraries using longjmp for error handlingKaz Kylheku
|  |  `* Re: Libraries using longjmp for error handlingTim Rentsch
|  |   +* Re: Libraries using longjmp for error handlingSpiros Bousbouras
|  |   |+* Re: Libraries using longjmp for error handlingTim Rentsch
|  |   ||+* Re: Libraries using longjmp for error handlingBen Bacarisse
|  |   |||+- Re: Libraries using longjmp for error handlingTim Rentsch
|  |   |||`- Re: Libraries using longjmp for error handlingKenny McCormack
|  |   ||`- Re: Libraries using longjmp for error handlingKaz Kylheku
|  |   |`* Re: Libraries using longjmp for error handlingAnton Shepelev
|  |   | `* Re: Libraries using longjmp for error handlingTim Rentsch
|  |   |  `- Re: Libraries using longjmp for error handlingKeith Thompson
|  |   `- Re: Libraries using longjmp for error handlingKaz Kylheku
|  +* Re: Libraries using longjmp for error handlingBen Bacarisse
|  |`* Re: Libraries using longjmp for error handlingKaz Kylheku
|  | `* Re: Libraries using longjmp for error handlingBen Bacarisse
|  |  +- Re: Libraries using longjmp for error handlingTim Rentsch
|  |  `* Re: Libraries using longjmp for error handlingKaz Kylheku
|  |   `* Re: Libraries using longjmp for error handlingAnton Shepelev
|  |    `- Re: Libraries using longjmp for error handlingTim Rentsch
|  `- Re: Libraries using longjmp for error handlingDavid Brown
`- Re: Libraries using longjmp for error handlingRichard Kettlewell

Pages:123
Re: Libraries using longjmp for error handling

<wwvil7sxdig.fsf@LkoBDZeT.terraraq.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29458&group=comp.lang.c#29458

  copy link   Newsgroups: news.software.nntp comp.lang.c
Path: i2pn2.org!i2pn.org!usenet.goja.nl.eu.org!nntp.terraraq.uk!.POSTED.tunnel.sfere.anjou.terraraq.org.uk!not-for-mail
From: inva...@invalid.invalid (Richard Kettlewell)
Newsgroups: news.software.nntp,comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sat, 30 Sep 2023 09:37:43 +0100
Organization: terraraq NNTP server
Message-ID: <wwvil7sxdig.fsf@LkoBDZeT.terraraq.uk>
References: <65SQM.565977$9o89.411905@fx05.ams4>
<wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk>
<pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Injection-Info: innmantic.terraraq.uk; posting-host="tunnel.sfere.anjou.terraraq.org.uk:172.17.207.6";
logging-data="114358"; mail-complaints-to="usenet@innmantic.terraraq.uk"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)
Cancel-Lock: sha1:+C7u7K71lS/9FNLh9qUvAXaiHb4=
X-Face: h[Hh-7npe<<b4/eW[]sat,I3O`t8A`(ej.H!F4\8|;ih)`7{@:A~/j1}gTt4e7-n*F?.Rl^
F<\{jehn7.KrO{!7=:(@J~]<.[{>v9!1<qZY,{EJxg6?Er4Y7Ng2\Ft>Z&W?r\c.!4DXH5PWpga"ha
+r0NzP?vnz:e/knOY)PI-
X-Boydie: NO
 by: Richard Kettlewell - Sat, 30 Sep 2023 08:37 UTC

Blue-Maned_Hawk <bluemanedhawk@invalid.invalid> writes:
> Richard Kettlewell wrote:
>> It’s more than 20 years since I last had to integrate a C library which
>> reported errors via longjmp() and I’m still bitter about it.
>
> I have never encountered a library which does that. Which library was
> that?

libpng

>> As a matter of API design, I’d rather C library communicated errors
>> via return values (and pointer parameters, where more complex error
>> information is required).
>
> Personally, i think that, at least for a library, an error should
> _only_ be communicated by return value. If more complex information
> is required, then the return value can be made more complex. I don't
> think i've ever used a library that communicates information via a
> pointer parameter.

Return value plus a pointer to additional information can certainly be
transformed into a struct containing both, though there’s an impact on
source code verbosity, object code size and performance.

For example if the extra information goes up to, say, 64 bytes, putting
it in a return value commits you to a 64-byte copy on every
return. However if it’s a pointer parameter, you only need to fill in
the fields relevant to the error that actually happened. In the happy
path, where there’s no error, that’s none of them.

--
https://www.greenend.org.uk/rjk/

Re: Libraries using longjmp for error handling

<87ttrbclcj.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29479&group=comp.lang.c#29479

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!news.hispagatos.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sun, 01 Oct 2023 00:06:20 +0100
Organization: A noiseless patient Spider
Lines: 63
Message-ID: <87ttrbclcj.fsf@bsb.me.uk>
References: <65SQM.565977$9o89.411905@fx05.ams4>
<wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk>
<pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid>
<AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk>
<86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk>
<86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk>
<86cyy0fee5.fsf@linuxsc.com>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="c2f22c1fb3b550915037b7b8f30f30b7";
logging-data="1243009"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+viGDMtOy8qZnmKJSAYtk+vERoBZvcCiI="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:5ExW2Tf/urIRPWa4+PyrVJoW7f4=
sha1:v178CgYsrLUZhd0RW83DcjxnLdY=
X-BSB-Auth: 1.8c97887c7e75bf6ca362.20231001000620BST.87ttrbclcj.fsf@bsb.me.uk
 by: Ben Bacarisse - Sat, 30 Sep 2023 23:06 UTC

Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>
>>> [..how should errors be handled..]
>>>
>>>> How would you prefer these sorts of thing to be signalled?
>>>
>>> Let me give just one example.
>>>
>>> I wrote some code not long ago to add a value to a set of values,
>>> where the set is represented using a recursive binary tree structure
>>> (like red-black trees, but a little different). Usually we may
>>> expect that a request to add a value would offer a value not already
>>> included in the set, but certainly it can happen that there is a
>>> call to add a value that is already included, in which case the top
>>> level return value should be the original tree structure.
>>>
>>> I thought it would be easier to write a simple recursive routine
>>> that assumes the to-be-added value is not yet included in the set,
>>> and if that assumption is violated raise an exception that is caught
>>> at the outermost level and simply returns the original argument tree
>>> value. Certainly the code could have been written to handle the
>>> already-present situation at each level of the recursion, but it was
>>> much easier and much cleaner to handle it by raising an exception.
>>
>> This is one of those cases where I just have to take your word for it,
>> (and I am happy to do that).
>
> Responding here to just this one part.
>
> Here is a simpler version of the code, for an ordinary
> binary tree, and without any rebalancing:
>
> module TreeSet = struct
> type 'a treeset = Empty | Node of 'a treeset * 'a * 'a treeset
> exception Present
>
> let add tree element =
> let rec add t e =
> match t with
> | Empty -> Node( Empty, e, Empty )
> | Node( a, v, b ) ->
> if e < v then Node( add a e, v, b ) else
> if e > v then Node( a, v, add b e ) else
> raise Present
> in
> try add tree element with Present -> tree
>
> end

I'm not getting it. I'd write 'else t' rather than 'else raise Present'
and I could then do away with the wrapping 'add' function.

I worry we are getting away from C, but the point is likely to be much
simpler to make in OCaml (or Caml).

--
Ben.

Re: Libraries using longjmp for error handling

<86r0mfdng1.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29484&group=comp.lang.c#29484

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sat, 30 Sep 2023 20:35:42 -0700
Organization: A noiseless patient Spider
Lines: 108
Message-ID: <86r0mfdng1.fsf@linuxsc.com>
References: <65SQM.565977$9o89.411905@fx05.ams4> <wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk> <pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid> <AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk> <86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk> <86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk> <86cyy0fee5.fsf@linuxsc.com> <87ttrbclcj.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="5df80bfa77615176987b6091c1d3373e";
logging-data="1466668"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19RmczlMOTMvDwlJ97BVbKUhe96vZX0fWI="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:M2E2svogUaGAK7vFE4WF5LDrO6Q=
sha1:+Q5GufpXsxcs0iAMMRubu9o+klE=
 by: Tim Rentsch - Sun, 1 Oct 2023 03:35 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>
>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>
>>>> [..how should errors be handled..]
>>>>
>>>>> How would you prefer these sorts of thing to be signalled?
>>>>
>>>> Let me give just one example.
>>>>
>>>> I wrote some code not long ago to add a value to a set of values,
>>>> where the set is represented using a recursive binary tree structure
>>>> (like red-black trees, but a little different). Usually we may
>>>> expect that a request to add a value would offer a value not already
>>>> included in the set, but certainly it can happen that there is a
>>>> call to add a value that is already included, in which case the top
>>>> level return value should be the original tree structure.
>>>>
>>>> I thought it would be easier to write a simple recursive routine
>>>> that assumes the to-be-added value is not yet included in the set,
>>>> and if that assumption is violated raise an exception that is caught
>>>> at the outermost level and simply returns the original argument tree
>>>> value. Certainly the code could have been written to handle the
>>>> already-present situation at each level of the recursion, but it was
>>>> much easier and much cleaner to handle it by raising an exception.
>>>
>>> This is one of those cases where I just have to take your word for it,
>>> (and I am happy to do that).
>>
>> Responding here to just this one part.
>>
>> Here is a simpler version of the code, for an ordinary
>> binary tree, and without any rebalancing:
>>
>> module TreeSet = struct
>> type 'a treeset = Empty | Node of 'a treeset * 'a * 'a treeset
>> exception Present
>>
>> let add tree element =
>> let rec add t e =
>> match t with
>> | Empty -> Node( Empty, e, Empty )
>> | Node( a, v, b ) ->
>> if e < v then Node( add a e, v, b ) else
>> if e > v then Node( a, v, add b e ) else
>> raise Present
>> in
>> try add tree element with Present -> tree
>>
>> end
>
> I'm not getting it. I'd write 'else t' rather than 'else raise
> Present' and I could then do away with the wrapping 'add' function.

Doing that would result in returning a valid tree, but it would also
needlessly replicate all nodes starting from the point where the
match was found and going up to the root. The consequence is more
cycles used and more demand on the memory allocator. The technique
of raising an exception avoids those shortcomings (and also it
preserves tree identity, which can be important in some situations).

> I worry we are getting away from C, but the point is likely to be
> much simpler to make in OCaml (or Caml).

I have another example. The example doesn't include any C code, but
I will talk about some concerns that pertain to C.

Suppose we are writing a compiler for a large programming language.
The compiler should make use of available resources, especially
memory resources, when it can, but also should be able to compile
large programs even when the amount of memory available is much more
limited. How much memory is available is not known in advance; we
find out when a call to malloc() or realloc() returns NULL. I note
in passing that the PL/I(F) compiler from IBM could translate full
PL/I even if limited to only 44 K bytes of user memory; to do that
it needed 110 physical passes over source text or structures created
and stored in disk files.

The idea in essence is to have two compilers in one: one taking a
conventional approach using regular dynamic memory allocation (in
other words malloc() etc), and the other using an IBM-style multiple
passes scheme that stores intermediate data in disk files. To
compile a program we start the first compiler under an umbrella of
setjmp(), which going forward assumes all memory allocations will
succeed. To allocate memory we call wrapper functions for malloc()
or realloc(), which will do a longjmp() if an allocation fails.
Upon receipt of the longjmp() "exception" the outer setjmp() call
starts over using the second approach, which is of course much
slower but also much less demanding of main memory.

To make this work we might have to track malloc()'s and free()'s so
that any not-yet-released memory can be reclaimed before beginning
the alternate system, but I think that is straightforward and not in
need of any further explanation.

I admit this example isn't very compelling given that even small
computers today have multiple gigabytes of RAM. But I think it
isn't hard to imagine an analogous problem in a more limited
environment, for example running in a VM on a co-located server.
(I have run out of "RAM" when running a program on my colo server
here. It was quite confusing when it first happened.)

Re: Libraries using longjmp for error handling

<86il7qekjo.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29486&group=comp.lang.c#29486

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sun, 01 Oct 2023 02:52:59 -0700
Organization: A noiseless patient Spider
Lines: 29
Message-ID: <86il7qekjo.fsf@linuxsc.com>
References: <65SQM.565977$9o89.411905@fx05.ams4> <wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk> <pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid> <AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk> <86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk> <86bkdlghqr.fsf@linuxsc.com> <20230929235846.a0883e001c83bbe718f5ab90@gmail.moc>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="5df80bfa77615176987b6091c1d3373e";
logging-data="1592466"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/ktx8kGdEcggQ1Mm1bIz1827lq53hWLhM="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:IJpOCy1+qE7YmfKeUmRX0tIx34I=
sha1:7ayo7tkOHqUDn2s/CK9loObKFm0=
 by: Tim Rentsch - Sun, 1 Oct 2023 09:52 UTC

Anton Shepelev <anton.txt@gmail.moc> writes:

> Tim Rentsch:
>
>> I wrote some code not long ago to add a value to a set of
>> values, where the set is represented using a recursive
>> binary tree structure (like red-black trees, but a little
>> different). Usually we may expect that a request to add a
>> value would offer a value not already included in the set,
>> but certainly it can happen that there is a call to add a
>> value that is already included, in which case the top
>> level return value should be the original tree structure.
>
> Returning an error flag (or code) all the way up the call
> stack may seem (and be) slow and cumbersome. If that case,
> one can rewrite the recursive function iteratively, with an
> explicit stack. I, however, think that an extra `if' in the
> recursive function is so much less fuss

Besides making the code slower and substantially longer,
the resulting code would take a lot more effort to read
and understand. In most cases lots of if()'s means the
code is poorly written and should be re-thought.

In this particular case re-writing the code to be iterative
rather than recursive, and using an explicit stack, is a
total non-starter. It's good to know the theoretical result
that recursion can be turned into iteration, but in practice
the two approaches are often not interchangeable.

Re: Libraries using longjmp for error handling

<20231001143351.8f3425bd90185668acd28809@gmail.moc>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29487&group=comp.lang.c#29487

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!news.hispagatos.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: anton....@gmail.moc (Anton Shepelev)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sun, 1 Oct 2023 14:33:51 +0300
Organization: A noiseless patient Spider
Lines: 61
Message-ID: <20231001143351.8f3425bd90185668acd28809@gmail.moc>
References: <65SQM.565977$9o89.411905@fx05.ams4>
<wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk>
<pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid>
<AE3RM.402236$kCld.195109@fx08.ams4>
<871qejf62x.fsf@bsb.me.uk>
<86y1gphiur.fsf@linuxsc.com>
<877co9d8m2.fsf@bsb.me.uk>
<86bkdlghqr.fsf@linuxsc.com>
<20230929235846.a0883e001c83bbe718f5ab90@gmail.moc>
<86il7qekjo.fsf@linuxsc.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Injection-Info: dont-email.me; posting-host="99cc9186fc8ebf6d6986a434d4cc8993";
logging-data="1630343"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18PRiFisnQkzM/bqXcaSSczlPjV5vf0lC0="
Cancel-Lock: sha1:tf/Y9zEbGBrN5LiYOltDE9kCUK0=
X-Newsreader: Sylpheed 3.7.0 (GTK+ 2.24.30; i686-pc-mingw32)
 by: Anton Shepelev - Sun, 1 Oct 2023 11:33 UTC

Tim Rentsch to Anton Shepelev:

> > Returning an error flag (or code) all the way up the
> > call stack may seem (and be) slow and cumbersome. If
> > that case, one can rewrite the recursive function
> > iteratively, with an explicit stack. I, however, think
> > that an extra `if' in the recursive function is so much
> > less fuss
>
> Besides making the code slower and substantially longer,

Substantially slower along the unhappy path only.
Substantially lobger -- I don't think so, because regardless
of recursion depth, there is just one recursive function,
and if you want to handle a single type of error, you would
need a single extra `if' in it.

> the resulting code would take a lot more effort to read
> and understand.

Explicit control of execution flow is clearer for several
reasons:

1. No out-of-bandwith signalling.

2. Errors are handled uniformly with any other condigions
in the program using the same basic facilities.

3. Errors are handled where they occur, in a manner
visible to the programmer reading the piece code that
may produce errors.

> In most cases lots of if()'s means the code is poorly
> written and should be re-thought.

Programms are all about logic, making decisions. It is not
the quantity, but the quality of `if's that may indicate a
flaw in coding, e.g. because of the failure to use dependeny
injection correctly, passing many flags into called
functions, &c. The if-else-if-else... chain discussed in a
parallel thread is itself a set of many nested if
statements, but it is not considered good or bad coding
based on its length.

> In this particular case re-writing the code to be
> iterative rather than recursive, and using an explicit
> stack, is a total non-starter.

Perhaps, I have not tried it. When, however, I rewrote
quicksort in a interative manner I actually like the result!

> It's good to know the theoretical result that recursion
> can be turned into iteration, but in practice the two
> approaches are often not interchangeable.

Indeed. Recursion for readability, iteration with a stack
for performance.

--
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments

Re: Libraries using longjmp for error handling

<20231001144405.3f6863a9af57ee632caaf74d@gmail.moc>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29488&group=comp.lang.c#29488

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: anton....@gmail.moc (Anton Shepelev)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sun, 1 Oct 2023 14:44:05 +0300
Organization: A noiseless patient Spider
Lines: 30
Message-ID: <20231001144405.3f6863a9af57ee632caaf74d@gmail.moc>
References: <65SQM.565977$9o89.411905@fx05.ams4>
<wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk>
<pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid>
<AE3RM.402236$kCld.195109@fx08.ams4>
<871qejf62x.fsf@bsb.me.uk>
<86y1gphiur.fsf@linuxsc.com>
<877co9d8m2.fsf@bsb.me.uk>
<86bkdlghqr.fsf@linuxsc.com>
<8734ywbvek.fsf@bsb.me.uk>
<86cyy0fee5.fsf@linuxsc.com>
<87ttrbclcj.fsf@bsb.me.uk>
<86r0mfdng1.fsf@linuxsc.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Injection-Info: dont-email.me; posting-host="99cc9186fc8ebf6d6986a434d4cc8993";
logging-data="1633903"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19+gun4v/fbnb7IpMJDhuIu/LFZyMbRL4Y="
Cancel-Lock: sha1:+TdYrNN8mZLOdQTKEuplHeNcVIE=
X-Newsreader: Sylpheed 3.7.0 (GTK+ 2.24.30; i686-pc-mingw32)
 by: Anton Shepelev - Sun, 1 Oct 2023 11:44 UTC

Tim Rentsch:

> The idea in essence is to have two compilers in one: one
> taking a conventional approach using regular dynamic
> memory allocation (in other words malloc() etc), and the
> other using an IBM-style multiple passes scheme that
> stores intermediate data in disk files. To compile a
> program we start the first compiler under an umbrella of
> setjmp(), which going forward assumes all memory
> allocations will succeed. To allocate memory we call
> wrapper functions for malloc() or realloc(), which will do
> a longjmp() if an allocation fails. Upon receipt of the
> longjmp() "exception" the outer setjmp() call starts over
> using the second approach, which is of course much slower
> but also much less demanding of main memory.
> [...]
> I admit this example isn't very compelling given that even
> small computers today have multiple gigabytes of RAM.

No, the availablity of lots of RAM in modern computers in
mere incidental to your example and in no way affects it.

How about this example: a recursive-descent parser for a
deeply nested grammar. How does one handle and reort an
error encountered ten invocations underground? Is it a
simpler example of the same problem?

--
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments

Re: Libraries using longjmp for error handling

<87il7qcsfz.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29490&group=comp.lang.c#29490

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sun, 01 Oct 2023 15:45:20 +0100
Organization: A noiseless patient Spider
Lines: 127
Message-ID: <87il7qcsfz.fsf@bsb.me.uk>
References: <65SQM.565977$9o89.411905@fx05.ams4>
<wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk>
<pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid>
<AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk>
<86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk>
<86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk>
<86cyy0fee5.fsf@linuxsc.com> <87ttrbclcj.fsf@bsb.me.uk>
<86r0mfdng1.fsf@linuxsc.com>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="c2f22c1fb3b550915037b7b8f30f30b7";
logging-data="1698119"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19iRdDhIrexSaQi6tM8oltZdpZwqVl/0Hw="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:ivSyfUlKkwlv+/KajbADQR+ZvM8=
sha1:0xi9g6MHjyOAVdWS/vzUFlFHNp4=
X-BSB-Auth: 1.0c2be7f648ba6632da6b.20231001154520BST.87il7qcsfz.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 1 Oct 2023 14:45 UTC

Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>
>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>
>>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>>
>>>>> [..how should errors be handled..]
>>>>>
>>>>>> How would you prefer these sorts of thing to be signalled?
>>>>>
>>>>> Let me give just one example.
>>>>>
>>>>> I wrote some code not long ago to add a value to a set of values,
>>>>> where the set is represented using a recursive binary tree structure
>>>>> (like red-black trees, but a little different). Usually we may
>>>>> expect that a request to add a value would offer a value not already
>>>>> included in the set, but certainly it can happen that there is a
>>>>> call to add a value that is already included, in which case the top
>>>>> level return value should be the original tree structure.
>>>>>
>>>>> I thought it would be easier to write a simple recursive routine
>>>>> that assumes the to-be-added value is not yet included in the set,
>>>>> and if that assumption is violated raise an exception that is caught
>>>>> at the outermost level and simply returns the original argument tree
>>>>> value. Certainly the code could have been written to handle the
>>>>> already-present situation at each level of the recursion, but it was
>>>>> much easier and much cleaner to handle it by raising an exception.
>>>>
>>>> This is one of those cases where I just have to take your word for it,
>>>> (and I am happy to do that).
>>>
>>> Responding here to just this one part.
>>>
>>> Here is a simpler version of the code, for an ordinary
>>> binary tree, and without any rebalancing:
>>>
>>> module TreeSet = struct
>>> type 'a treeset = Empty | Node of 'a treeset * 'a * 'a treeset
>>> exception Present
>>>
>>> let add tree element =
>>> let rec add t e =
>>> match t with
>>> | Empty -> Node( Empty, e, Empty )
>>> | Node( a, v, b ) ->
>>> if e < v then Node( add a e, v, b ) else
>>> if e > v then Node( a, v, add b e ) else
>>> raise Present
>>> in
>>> try add tree element with Present -> tree
>>>
>>> end
>>
>> I'm not getting it. I'd write 'else t' rather than 'else raise
>> Present' and I could then do away with the wrapping 'add' function.
>
> Doing that would result in returning a valid tree, but it would also
> needlessly replicate all nodes starting from the point where the
> match was found and going up to the root. The consequence is more
> cycles used and more demand on the memory allocator.

How can OCaml avoid making the allocations until it knows the exception
won't be raised? Are they not all still being done?

> The technique
> of raising an exception avoids those shortcomings (and also it
> preserves tree identity, which can be important in some situations).

I agree about the identity. I am not used to relying on the identity in
situations like this (probably because of Haskell!) but I might find
some time to work out how to preserve identity without an exception. I
fear it will be messier that your simple solution.

>> I worry we are getting away from C, but the point is likely to be
>> much simpler to make in OCaml (or Caml).
>
> I have another example. The example doesn't include any C code, but
> I will talk about some concerns that pertain to C.
>
> Suppose we are writing a compiler for a large programming language.
> The compiler should make use of available resources, especially
> memory resources, when it can, but also should be able to compile
> large programs even when the amount of memory available is much more
> limited. How much memory is available is not known in advance; we
> find out when a call to malloc() or realloc() returns NULL. I note
> in passing that the PL/I(F) compiler from IBM could translate full
> PL/I even if limited to only 44 K bytes of user memory; to do that
> it needed 110 physical passes over source text or structures created
> and stored in disk files.
>
> The idea in essence is to have two compilers in one: one taking a
> conventional approach using regular dynamic memory allocation (in
> other words malloc() etc), and the other using an IBM-style multiple
> passes scheme that stores intermediate data in disk files. To
> compile a program we start the first compiler under an umbrella of
> setjmp(), which going forward assumes all memory allocations will
> succeed. To allocate memory we call wrapper functions for malloc()
> or realloc(), which will do a longjmp() if an allocation fails.
> Upon receipt of the longjmp() "exception" the outer setjmp() call
> starts over using the second approach, which is of course much
> slower but also much less demanding of main memory.
>
> To make this work we might have to track malloc()'s and free()'s so
> that any not-yet-released memory can be reclaimed before beginning
> the alternate system, but I think that is straightforward and not in
> need of any further explanation.

I am not convinced it's neater to use longjmp here. I prefer to write
code where allocation failures just propagate up the call stack. That
would give me a top-level failure return from the try_fast_compile()
function call.

> I admit this example isn't very compelling given that even small
> computers today have multiple gigabytes of RAM. But I think it
> isn't hard to imagine an analogous problem in a more limited
> environment, for example running in a VM on a co-located server.
> (I have run out of "RAM" when running a program on my colo server
> here. It was quite confusing when it first happened.)

--
Ben.

Re: Libraries using longjmp for error handling

<86ediee28o.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29492&group=comp.lang.c#29492

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sun, 01 Oct 2023 09:28:23 -0700
Organization: A noiseless patient Spider
Lines: 220
Message-ID: <86ediee28o.fsf@linuxsc.com>
References: <65SQM.565977$9o89.411905@fx05.ams4> <wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk> <pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid> <AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk> <86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk> <86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk> <86cyy0fee5.fsf@linuxsc.com> <87ttrbclcj.fsf@bsb.me.uk> <86r0mfdng1.fsf@linuxsc.com> <87il7qcsfz.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="5df80bfa77615176987b6091c1d3373e";
logging-data="1736391"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18qKmSB3d1Nsgjge2wTCxQlPdzv0GQi7D0="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:4f5LwAg6viYffFTpk5HkP6zT6vU=
sha1:QURjTR8eFB9rFUFmWF/pnC+VwjU=
 by: Tim Rentsch - Sun, 1 Oct 2023 16:28 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>
>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>
>>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>>
>>>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>>>
>>>>>> [..how should errors be handled..]
>>>>>>
>>>>>>> How would you prefer these sorts of thing to be signalled?
>>>>>>
>>>>>> Let me give just one example.
>>>>>>
>>>>>> I wrote some code not long ago to add a value to a set of values,
>>>>>> where the set is represented using a recursive binary tree structure
>>>>>> (like red-black trees, but a little different). Usually we may
>>>>>> expect that a request to add a value would offer a value not already
>>>>>> included in the set, but certainly it can happen that there is a
>>>>>> call to add a value that is already included, in which case the top
>>>>>> level return value should be the original tree structure.
>>>>>>
>>>>>> I thought it would be easier to write a simple recursive routine
>>>>>> that assumes the to-be-added value is not yet included in the set,
>>>>>> and if that assumption is violated raise an exception that is caught
>>>>>> at the outermost level and simply returns the original argument tree
>>>>>> value. Certainly the code could have been written to handle the
>>>>>> already-present situation at each level of the recursion, but it was
>>>>>> much easier and much cleaner to handle it by raising an exception.
>>>>>
>>>>> This is one of those cases where I just have to take your word for it,
>>>>> (and I am happy to do that).
>>>>
>>>> Responding here to just this one part.
>>>>
>>>> Here is a simpler version of the code, for an ordinary
>>>> binary tree, and without any rebalancing:
>>>>
>>>> module TreeSet = struct
>>>> type 'a treeset = Empty | Node of 'a treeset * 'a * 'a treeset
>>>> exception Present
>>>>
>>>> let add tree element =
>>>> let rec add t e =
>>>> match t with
>>>> | Empty -> Node( Empty, e, Empty )
>>>> | Node( a, v, b ) ->
>>>> if e < v then Node( add a e, v, b ) else
>>>> if e > v then Node( a, v, add b e ) else
>>>> raise Present
>>>> in
>>>> try add tree element with Present -> tree
>>>>
>>>> end
>>>
>>> I'm not getting it. I'd write 'else t' rather than 'else raise
>>> Present' and I could then do away with the wrapping 'add' function.
>>
>> Doing that would result in returning a valid tree, but it would also
>> needlessly replicate all nodes starting from the point where the
>> match was found and going up to the root. The consequence is more
>> cycles used and more demand on the memory allocator.
>
> How can OCaml avoid making the allocations until it knows the exception
> won't be raised? Are they not all still being done?

No, no allocations are done if the to-be-added element is found
(and so an exception is raised). Consider one of the lines where a
Node is being constructed (which is synonymous with an allocation
occurring):

if e < v then Node( add a e, v, b ) else

The call to the Node() constructor doesn't take place until the
recursive call to 'add' returns. But if an equal value is found,
then an exception is raised, and the call to 'add' does not /ever/
return. No return from 'add' means no Node() is constructed.

To say this another way, looking for a point where an insertion
should take place, or where there is an equal value, happens going
/down/ the call chain. Node() allocations, however, happen only
when we are coming back /up/ the call chain. Raising an exception
"short circuits" all of those pending returns: they never happen,
and so no Node()s are constructed.

>> The technique
>> of raising an exception avoids those shortcomings (and also it
>> preserves tree identity, which can be important in some situations).
>
> I agree about the identity. I am not used to relying on the identity in
> situations like this (probably because of Haskell!) but I might find
> some time to work out how to preserve identity without an exception. I
> fear it will be messier that your simple solution.

SPOILER ALERT - at the end of this posting I am including code
for a version of add (called add') that does not use exceptions
and preserves identity when the "new" element is already present.

>>> I worry we are getting away from C, but the point is likely to be
>>> much simpler to make in OCaml (or Caml).
>>
>> I have another example. The example doesn't include any C code, but
>> I will talk about some concerns that pertain to C.
>>
>> Suppose we are writing a compiler for a large programming language.
>> The compiler should make use of available resources, especially
>> memory resources, when it can, but also should be able to compile
>> large programs even when the amount of memory available is much more
>> limited. How much memory is available is not known in advance; we
>> find out when a call to malloc() or realloc() returns NULL. I note
>> in passing that the PL/I(F) compiler from IBM could translate full
>> PL/I even if limited to only 44 K bytes of user memory; to do that
>> it needed 110 physical passes over source text or structures created
>> and stored in disk files.
>>
>> The idea in essence is to have two compilers in one: one taking a
>> conventional approach using regular dynamic memory allocation (in
>> other words malloc() etc), and the other using an IBM-style multiple
>> passes scheme that stores intermediate data in disk files. To
>> compile a program we start the first compiler under an umbrella of
>> setjmp(), which going forward assumes all memory allocations will
>> succeed. To allocate memory we call wrapper functions for malloc()
>> or realloc(), which will do a longjmp() if an allocation fails.
>> Upon receipt of the longjmp() "exception" the outer setjmp() call
>> starts over using the second approach, which is of course much
>> slower but also much less demanding of main memory.
>>
>> To make this work we might have to track malloc()'s and free()'s so
>> that any not-yet-released memory can be reclaimed before beginning
>> the alternate system, but I think that is straightforward and not in
>> need of any further explanation.
>
> I am not convinced it's neater to use longjmp here. I prefer to write
> code where allocation failures just propagate up the call stack. That
> would give me a top-level failure return from the try_fast_compile()
> function call.

There was a time when I would normally handle unusual conditions
locally, and pooh-poohed using exceptions (and setjmp()/longjmp()).
Working in OCaml has caused me (I speculate) to revise my thoughts
on the question.

SPOILER ALERT - continue scrolling only when ready to see the code
for an exception-free version of the add function...

Here it is...

let add' tree element =
let rec add t e =
match t with
| Empty -> Some (Node( Empty, e, Empty ))
| Node( a, v, b ) ->
if e < v then (
match add a e with
| None -> None
| Some a' -> Some( Node( a', v, b ) )
) else if e > v then (
match add b e with
| None -> None
| Some b' -> Some( Node( a, v, b' ) )
) else None
in
match add tree element with
| Some t -> t
| None -> tree

The original version is 10 lines, the revised version 18 lines.

That ratio is higher than what I would expect for an analogous
change to the full version (which is much longer than the simple
non-rebalancing version, because it has more cases to deal with,
and needs to keep the tree balanced), but not a lot higher - maybe
only 40 or 50% longer instead of 80% longer.


Click here to read the complete article
Re: Libraries using longjmp for error handling

<874jjaced5.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29495&group=comp.lang.c#29495

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Sun, 01 Oct 2023 20:49:26 +0100
Organization: A noiseless patient Spider
Lines: 91
Message-ID: <874jjaced5.fsf@bsb.me.uk>
References: <65SQM.565977$9o89.411905@fx05.ams4>
<wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk>
<pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid>
<AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk>
<86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk>
<86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk>
<86cyy0fee5.fsf@linuxsc.com> <87ttrbclcj.fsf@bsb.me.uk>
<86r0mfdng1.fsf@linuxsc.com> <87il7qcsfz.fsf@bsb.me.uk>
<86ediee28o.fsf@linuxsc.com>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="c2f22c1fb3b550915037b7b8f30f30b7";
logging-data="2604652"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18YpQgS0i5lepj6oVEeBS+byBXfngXCSdY="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:RnSRimHGCaoUB4cNNQQqyRiaYis=
sha1:M8RkcLEr2RF1glc0ml5htPBBzVw=
X-BSB-Auth: 1.4efb2bc73e14e820a3c3.20231001204926BST.874jjaced5.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 1 Oct 2023 19:49 UTC

Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>
>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>
>>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>>
>>>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>>>
>>>>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>>>>
>>>>>>> [..how should errors be handled..]
>>>>>>>
>>>>>>>> How would you prefer these sorts of thing to be signalled?
>>>>>>>
>>>>>>> Let me give just one example.
>>>>>>>
>>>>>>> I wrote some code not long ago to add a value to a set of values,
>>>>>>> where the set is represented using a recursive binary tree structure
>>>>>>> (like red-black trees, but a little different). Usually we may
>>>>>>> expect that a request to add a value would offer a value not already
>>>>>>> included in the set, but certainly it can happen that there is a
>>>>>>> call to add a value that is already included, in which case the top
>>>>>>> level return value should be the original tree structure.
>>>>>>>
>>>>>>> I thought it would be easier to write a simple recursive routine
>>>>>>> that assumes the to-be-added value is not yet included in the set,
>>>>>>> and if that assumption is violated raise an exception that is caught
>>>>>>> at the outermost level and simply returns the original argument tree
>>>>>>> value. Certainly the code could have been written to handle the
>>>>>>> already-present situation at each level of the recursion, but it was
>>>>>>> much easier and much cleaner to handle it by raising an exception.
>>>>>>
>>>>>> This is one of those cases where I just have to take your word for it,
>>>>>> (and I am happy to do that).
>>>>>
>>>>> Responding here to just this one part.
>>>>>
>>>>> Here is a simpler version of the code, for an ordinary
>>>>> binary tree, and without any rebalancing:
>>>>>
>>>>> module TreeSet = struct
>>>>> type 'a treeset = Empty | Node of 'a treeset * 'a * 'a treeset
>>>>> exception Present
>>>>>
>>>>> let add tree element =
>>>>> let rec add t e =
>>>>> match t with
>>>>> | Empty -> Node( Empty, e, Empty )
>>>>> | Node( a, v, b ) ->
>>>>> if e < v then Node( add a e, v, b ) else
>>>>> if e > v then Node( a, v, add b e ) else
>>>>> raise Present
>>>>> in
>>>>> try add tree element with Present -> tree
>>>>>
>>>>> end
>>>>
>>>> I'm not getting it. I'd write 'else t' rather than 'else raise
>>>> Present' and I could then do away with the wrapping 'add' function.
>>>
>>> Doing that would result in returning a valid tree, but it would also
>>> needlessly replicate all nodes starting from the point where the
>>> match was found and going up to the root. The consequence is more
>>> cycles used and more demand on the memory allocator.
>>
>> How can OCaml avoid making the allocations until it knows the exception
>> won't be raised? Are they not all still being done?
>
> No, no allocations are done if the to-be-added element is found
> (and so an exception is raised). Consider one of the lines where a
> Node is being constructed (which is synonymous with an allocation
> occurring):
>
> if e < v then Node( add a e, v, b ) else
>
> The call to the Node() constructor doesn't take place until the
> recursive call to 'add' returns. But if an equal value is found,
> then an exception is raised, and the call to 'add' does not /ever/
> return. No return from 'add' means no Node() is constructed.

Ah, yes. I was thinking in a lazy language (Haskell) whilst looking at
code in a strict one.

--
Ben.

Re: Libraries using longjmp for error handling

<865y3pe5gc.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29496&group=comp.lang.c#29496

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Mon, 02 Oct 2023 02:31:15 -0700
Organization: A noiseless patient Spider
Lines: 65
Message-ID: <865y3pe5gc.fsf@linuxsc.com>
References: <65SQM.565977$9o89.411905@fx05.ams4> <wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk> <pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid> <AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk> <86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk> <86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk> <86cyy0fee5.fsf@linuxsc.com> <87ttrbclcj.fsf@bsb.me.uk> <86r0mfdng1.fsf@linuxsc.com> <87il7qcsfz.fsf@bsb.me.uk> <86ediee28o.fsf@linuxsc.com> <874jjaced5.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="65a81d1645349794f5679002e479c951";
logging-data="3033032"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+CynV4i/EunwZgyuqrUIC3o9l2VZMQnYQ="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:SHAw3Z6VDqhECYzQ68lQbTHacC4=
sha1:TWz2WBgUnDBgwkyJ8QxwhO7tGqw=
 by: Tim Rentsch - Mon, 2 Oct 2023 09:31 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>
>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>
>>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
[...]
>>>>>> [..example to illustrate using exceptions..]
>>>>>>
>>>>>> module TreeSet = struct
>>>>>> type 'a treeset = Empty | Node of 'a treeset * 'a * 'a treeset
>>>>>> exception Present
>>>>>>
>>>>>> let add tree element =
>>>>>> let rec add t e =
>>>>>> match t with
>>>>>> | Empty -> Node( Empty, e, Empty )
>>>>>> | Node( a, v, b ) ->
>>>>>> if e < v then Node( add a e, v, b ) else
>>>>>> if e > v then Node( a, v, add b e ) else
>>>>>> raise Present
>>>>>> in
>>>>>> try add tree element with Present -> tree
>>>>>>
>>>>>> end
>>>>>
>>>>> I'm not getting it. I'd write 'else t' rather than 'else raise
>>>>> Present' and I could then do away with the wrapping 'add' function.
>>>>
>>>> Doing that would result in returning a valid tree, but it would also
>>>> needlessly replicate all nodes starting from the point where the
>>>> match was found and going up to the root. The consequence is more
>>>> cycles used and more demand on the memory allocator.
>>>
>>> How can OCaml avoid making the allocations until it knows the exception
>>> won't be raised? Are they not all still being done?
>>
>> No, no allocations are done if the to-be-added element is found
>> (and so an exception is raised). Consider one of the lines where a
>> Node is being constructed (which is synonymous with an allocation
>> occurring):
>>
>> if e < v then Node( add a e, v, b ) else
>>
>> The call to the Node() constructor doesn't take place until the
>> recursive call to 'add' returns. But if an equal value is found,
>> then an exception is raised, and the call to 'add' does not /ever/
>> return. No return from 'add' means no Node() is constructed.
>
> Ah, yes. I was thinking in a lazy language (Haskell) while looking at
> code in a strict one.

Right. I was wondering if that might be the source of the
confusion. Now that the question has come up, I don't know what
it means to raise an exception in a language like Haskell where
lazy evaluation is always in force. Does Haskell have exceptions?

C is like OCaml in this respect in that lazy eval is possible but
it needs to be explicit rather than just happening everywhere
automatically.

Re: Libraries using longjmp for error handling

<87o7hgbpmz.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29499&group=comp.lang.c#29499

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Mon, 02 Oct 2023 23:55:48 +0100
Organization: A noiseless patient Spider
Lines: 76
Message-ID: <87o7hgbpmz.fsf@bsb.me.uk>
References: <65SQM.565977$9o89.411905@fx05.ams4>
<wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk>
<pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid>
<AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk>
<86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk>
<86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk>
<86cyy0fee5.fsf@linuxsc.com> <87ttrbclcj.fsf@bsb.me.uk>
<86r0mfdng1.fsf@linuxsc.com> <87il7qcsfz.fsf@bsb.me.uk>
<86ediee28o.fsf@linuxsc.com> <874jjaced5.fsf@bsb.me.uk>
<865y3pe5gc.fsf@linuxsc.com>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="8bb06864c657a93e3140d2f2dc1fdc45";
logging-data="3331226"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX191wErJyu6LH8QST17++xX/cjgDrXB9HTg="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:mkktEpjMghL04oK1vdhH3waiI6M=
sha1:+S1pLNo3pijzpohPZx36qTh/T5w=
X-BSB-Auth: 1.3bc005d66b30e1992608.20231002235548BST.87o7hgbpmz.fsf@bsb.me.uk
 by: Ben Bacarisse - Mon, 2 Oct 2023 22:55 UTC

Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>
>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>
>>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>>
>>>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> [...]
>>>>>>> [..example to illustrate using exceptions..]
>>>>>>>
>>>>>>> module TreeSet = struct
>>>>>>> type 'a treeset = Empty | Node of 'a treeset * 'a * 'a treeset
>>>>>>> exception Present
>>>>>>>
>>>>>>> let add tree element =
>>>>>>> let rec add t e =
>>>>>>> match t with
>>>>>>> | Empty -> Node( Empty, e, Empty )
>>>>>>> | Node( a, v, b ) ->
>>>>>>> if e < v then Node( add a e, v, b ) else
>>>>>>> if e > v then Node( a, v, add b e ) else
>>>>>>> raise Present
>>>>>>> in
>>>>>>> try add tree element with Present -> tree
>>>>>>>
>>>>>>> end
>>>>>>
>>>>>> I'm not getting it. I'd write 'else t' rather than 'else raise
>>>>>> Present' and I could then do away with the wrapping 'add' function.
>>>>>
>>>>> Doing that would result in returning a valid tree, but it would also
>>>>> needlessly replicate all nodes starting from the point where the
>>>>> match was found and going up to the root. The consequence is more
>>>>> cycles used and more demand on the memory allocator.
>>>>
>>>> How can OCaml avoid making the allocations until it knows the exception
>>>> won't be raised? Are they not all still being done?
>>>
>>> No, no allocations are done if the to-be-added element is found
>>> (and so an exception is raised). Consider one of the lines where a
>>> Node is being constructed (which is synonymous with an allocation
>>> occurring):
>>>
>>> if e < v then Node( add a e, v, b ) else
>>>
>>> The call to the Node() constructor doesn't take place until the
>>> recursive call to 'add' returns. But if an equal value is found,
>>> then an exception is raised, and the call to 'add' does not /ever/
>>> return. No return from 'add' means no Node() is constructed.
>>
>> Ah, yes. I was thinking in a lazy language (Haskell) while looking at
>> code in a strict one.
>
> Right. I was wondering if that might be the source of the
> confusion. Now that the question has come up, I don't know what
> it means to raise an exception in a language like Haskell where
> lazy evaluation is always in force. Does Haskell have exceptions?

Yes it does, but I have not really wrapped my head around them. They
throw you into the IO monad.

> C is like OCaml in this respect in that lazy eval is possible but
> it needs to be explicit rather than just happening everywhere
> automatically.

I knew OCaml was strict, I just had the wrong head on because the type
system and matching are so similar.

--
Ben.

Re: Libraries using longjmp for error handling

<86o7hfdieg.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=29503&group=comp.lang.c#29503

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!news.hispagatos.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Libraries using longjmp for error handling
Date: Tue, 03 Oct 2023 05:01:27 -0700
Organization: A noiseless patient Spider
Lines: 25
Message-ID: <86o7hfdieg.fsf@linuxsc.com>
References: <65SQM.565977$9o89.411905@fx05.ams4> <wwvpm23d9fr.fsf@LkoBDZeT.terraraq.uk> <pan$6f4ce$6edf891e$2b5c40c1$f8f989c1@invalid.invalid> <AE3RM.402236$kCld.195109@fx08.ams4> <871qejf62x.fsf@bsb.me.uk> <86y1gphiur.fsf@linuxsc.com> <877co9d8m2.fsf@bsb.me.uk> <86bkdlghqr.fsf@linuxsc.com> <8734ywbvek.fsf@bsb.me.uk> <86cyy0fee5.fsf@linuxsc.com> <87ttrbclcj.fsf@bsb.me.uk> <86r0mfdng1.fsf@linuxsc.com> <87il7qcsfz.fsf@bsb.me.uk> <86ediee28o.fsf@linuxsc.com> <874jjaced5.fsf@bsb.me.uk> <865y3pe5gc.fsf@linuxsc.com> <87o7hgbpmz.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="a7f15c7033ff7991d1a910385a293cab";
logging-data="3730258"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18u2zAiCaaZ1NSY1oDFBkCeseHWE3plvFE="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:/1VQ/SHigIdKOV3C0sh+JkgI1KA=
sha1:m4nsTGalBN1UwV9vIlWjUVObRc0=
 by: Tim Rentsch - Tue, 3 Oct 2023 12:01 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

[..setjmp()/longjmp() in other languages..]

>>> Ah, yes. I was thinking in a lazy language (Haskell) while
>>> looking at code in a strict one.
>>
>> Right. I was wondering if that might be the source of the
>> confusion. Now that the question has come up, I don't know what
>> it means to raise an exception in a language like Haskell where
>> lazy evaluation is always in force. Does Haskell have exceptions?
>
> Yes it does, but I have not really wrapped my head around them.
> They throw you into the IO monad.

I see. :) Thank you for the info.

It might be interesting to speculate what C would be like
if it were lazy rather than eager. Maybe a lazy C could
have the property that undefined behavior wouldn't happen
unless it became essential to producing an output. Hmmm..

Pages:123
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor