:: Re: [DNG] C exception handling
Inizio della pagina
Delete this message
Reply to this message
Autore: nick
Data:  
To: dng
Oggetto: Re: [DNG] C exception handling


Karl, Didier,



I can definitely see both sides of this issue. There is probably a place for error handling macros. To see a non trivial codebase where error handling macros are used throughout:

https://github.com/espressif/esp-idf

They have macros like ESP_RETURN_ON_FAILURE() and similar macros for goto on failure and with or without logging. Most functions return esp_err_t and logging is standardized based on a static symbol called TAG in each file. These conventions make it manageable.



Having said that, when I am writing embedded code to run under IDF, I don't use their macros. I write things out the long way because I find it hard to remember all their combinations and I find the long way more readable. Also I am currently working on code that can run with or without IDF depending on the MCU I'm compiling for. So I use my conventions. If I was to submit PRs to the IDF repo then I'd have to use IDF conventions though. So it's case by case.



I also want to share a technique that I picked up in the university research environment. I worked with a dude who was a kind of a wayward genius, he was quite lazy and sloppy and had an abrasive personality but he was super productive, he wrote a lot of papers and won awards and stuff so I could overlook his peccadillos. In research you are basically testing an idea so it's good to smash out a lot of code quickly and avoid gold plating (a term that was bandied about a lot -- and as a perfectionist I find it very conflicting, but I digress). Anyway so this guy would use assertions instead of proper error checking but with a differently named macro:

char *p = strdup("This is a string");

rassert(p != NULL);

The name rassert() means "run time assert" and it is an assertion that is always present, even in release builds, ie a failure does not indicate a coding error but an issue with the external environment that we do not control. I usually create the rassert() macro by hacking on the system's assert.h to create a copy called rassert.h that ignores the NDEBUG processor symbol (that is defined in a release build to suppress assertions). This way I can reuse the system's assert handler and get nicely printed messages. And when something does go wrong it quickly takes me to the failing code. So it's exactly like an uncaught exception really.



I don't like the idea of using setjmp/longjmp routinely for this kind of purpose though. That's because setjmp/longjmp are implemented in a kind of a hacky way where the stack pointer and certain registers are stored in the jmp_buf structure at setjmp time (actually an array) and restored at longjmp time. But this has some weird consequences. Register variables will revert to their values from setjmp time, as longjmp doesn't know where their real values are saved. And if the setjmp call occurred within an expression then it will try to calculate the expression again at longjmp time but the partial results will have been corrupted in the meantime by the reuse of the stack. I believe current C standards place restrictions on how setjmp can be called for that reason. And probably modern compilers suppress most optimizations in routines with setjmp.



For a while I toyed with the idea of making a source to source translator that could add exception handling to C using setjmp/longjmp but eventually I decided a safer way would be to munge every function signature so that the original return value becomes an out parameter (the caller provides a pointer to say where they want the function result placed) and the return value instead gives the error status -- which could be a simple bool, an errno similar to unix errno or esp_err_t mentioned above, or a pointer to an exception object. The required translation is not trivial though, as expressions containing function calls must be broken down into separate statements and when they occur within a control structure like a C for-loop, this has to be emulated using gotos or similar means.



Overall, the easiest way IMO is to write out the error handling code longhand. Or use Python, Ada, etc. Sigh. I love C but there is definitely a love/hate aspect to it sometimes.



Kind regards, Nick








>
> On 27 Oct 2024 at 11:00 pm, dng-request <dng-request@???> wrote:
>
>
> Send Dng mailing list submissions to
> dng@???
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
> or, via email, send a message with subject or body 'help' to
> dng-request@???
>
> You can reach the person managing the list at
> dng-owner@???
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Dng digest..."
>
>
> Today's Topics:
>
> 1. Re: Installation of Fluxbox (fsmithred)
> 2. Re: Error handling alternatives (was Re: another programming
> language question) (Didier Kryn)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Sat, 26 Oct 2024 10:01:13 -0400
> From: fsmithred <fsmithred@???>
> To: dng@???
> Subject: Re: [DNG] Installation of Fluxbox
> Message-ID: <0a9ffa4c-20f7-4219-b427-0c5a9752a49d@???>
> Content-Type: text/plain; charset=UTF-8; format=flowed
>
> On 10/26/24 04:28, Haines Brown via Dng wrote:
> > On a new installation of the Daedalus, in order to start the fluxbox
> > window manager I must do:
> >
> > $ startx fluxbox
> >
> > I set Fluxbox to be default window manager with
> >
> > # update-alternatives --config x-window-manager
> >
>
> I tried this, and I get the same result as you. Just running 'startx' by
> itself brings up the xfce4 desktop (which is blue). I tried changing the
> session manager with
>
> # update-alternatives --config x-session-manager
>
> but all three choices were xfce4. So I then removed xfce4-session which
> pulled a few other things out with it. There are no longer any choices for
> x-session-manager and running 'startx' starts fluxbox.
>
> I did not do anything with other files such as .xinitrc or .xsession.
>
> I tried running 'startxfce4' but that command is gone. If I re-enable
> slim, it logs me into fluxbox, and F1 shows no other session choices but
> fluxbox.
>
> fsmithred
>
>
> ------------------------------
>
> Message: 2
> Date: Sun, 27 Oct 2024 12:04:16 +0100
> From: Didier Kryn <kryn@???>
> To: dng@???
> Subject: Re: [DNG] Error handling alternatives (was Re: another
> programming language question)
> Message-ID: <848165a6-c370-4464-80be-8fcce8fedfca@???>
> Content-Type: text/plain; charset=UTF-8; format=flowed
>
> Le 26/10/2024 ? 11:38, karl@??? a ?crit?:
> > Karl:
> > ...
> >
> > this code:
> > LOG_VIF( cnti != cnto, LOG_ERR, " cnti = %ld, cnto = %ld", cnti, cnto ) { return -1; }
> > gives this:
> >> 2024-10-16_21:33:53: ERR run.c 62: <cnti != cnto> cnti = 0, cnto = 3
> > ...
> >
> > when the test failed. I.e. I can see a copy of the actual test:
> > "cnti != cnto" in the log. I get that by including a copy of
> > the test "f" text in the printout:
> >
> > #define LOG_VIF( f, lvl, format, ... ) \
> > if ( (f) && ( LOG_PRINTF(lvl, "<%s>" format, #f, __VA_ARGS__), 1 ) )
> >
> > Can I get that in ADA too ?
> >
> > I think it is nice to see the actual test that triggered the log line
> > in the log.
> >
> ??? Karl, it is difficult to follow you into your cpp macros. Also,
> this shouldn't turn to a lecture on Ada because both it would be very
> off topic, and I'm not ready for that.
>
> ??? You are relying on preprocessor macros to do things C proper cannot
> do. This is a dead-end and you know it. Preprocessor macros must be used
> with moderation. They undergo no syntax analysis and the compiler
> diagnostics is made on the expanded code instead of your actual source.
> If you are counting on these tricks, it means you have hit the maximum
> level of complexity which can reasonably be reached with this language.
>
> ??? However there is another technique which can be used in C to let
> exceptions follow a different flow path, and is implemented in the
> runtime library. This is the setjmp/longjmp technique; I have no
> experience with it but I understand that's roughly what it's intended
> for. I think it's the only way to implement a smarter exception handling
> in C, though, as usual in C, you need to carve it all by hand. I do
> think it's the best C can give you in this matter.
>
> -- ??? Didier
>
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> Dng mailing list
> Dng@???
> Manage your subscription: https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
> Archive: https://lists.dyne.org/lurker/list/dng.en.html
>
>
> ------------------------------
>
> End of Dng Digest, Vol 121, Issue 63
> ************************************
>