Didier:
...
> Â Â Â One of the other important features of high-level languages is to
> let exceptions take a separate flow path. In C, the errors are generally
> reported in the return value of a function: a meaningless value or a
> non-zero value is what tells you there was an error. Therefore a correct
> program always checks that the return value does not signal an error,
> and this clobbers your algorithm with error checks and conditional
> branchings. It makes your source bigger and painfull to read.
...
If you enclose more than a few lines of code in a try block, then you
will loose the sense of where it happened.
To solve that I have made some macros [1] so you always can check
the return value without much clutter. From what I understand you
cannot do something similar in e.g. ada, leading you to more clutter
or the habit of enclosing bigger chunks of code in try/catch or
altogether skipping it, which to me seems to be just as bad as
ignoring the return value.
With my macro set:
LOG_IFERRNO( sigemptyset(&sa.sa_mask) , LOG_CRIT ) { return -1; }
LOG_IFERRNO( sigaddsetM(&sa.sa_mask, set), LOG_CRIT ) { return -1; }
for (pp = set; *pp; pp++) {
LOG_VIFERRNO( sigaction(*pp, &sa, NULL), LOG_ERR, " *pp = %d", *pp ) {
return -1;
}
}
I can check and report about every error return without much clutter.
To do the same thing with exceptions in some hypotetical language is
much more cluttersome:
begin
sigemptyset(&sa.sa_mask);
catch
log(...);
raise again;
end
begin
sigaddsetM(&sa.sa_mask, set);
catch
log(some more);
raise again;
end
for (pp = set; *pp; pp++)
begin
begin
sigaction(*pp, &sa, NULL);
catch
log(even more);
raise again;
end
end
On the other hand, handling divide by 0, floating point errors and
segment violations via signals and longjump() isn't very nice.
Regards,
/Karl Hammar
[1]
https://aspodata.se/git/c/libaspoutil/log_util.h and log_util.c