Re: else ladders practice

Liste des GroupesRevenir à cl c 
Sujet : Re: else ladders practice
De : antispam (at) *nospam* fricas.org (Waldek Hebisch)
Groupes : comp.lang.c
Date : 20. Nov 2024, 19:31:53
Autres entêtes
Organisation : To protect and to server
Message-ID : <vhl9um$358bt$1@paganini.bofh.team>
References : 1 2 3 4 5 6 7 8 9 10 11 12 13 14
User-Agent : tin/2.6.2-20221225 ("Pittyvaich") (Linux/6.1.0-9-amd64 (x86_64))
David Brown <david.brown@hesbynett.no> wrote:
On 15/11/2024 19:50, Waldek Hebisch wrote:
David Brown <david.brown@hesbynett.no> wrote:
On 11/11/2024 20:09, Waldek Hebisch wrote:
David Brown <david.brown@hesbynett.no> wrote:
>
Concerning correct place for checks: one could argue that check
should be close to place where the result of check matters, which
frequently is in called function.
>
No, there I disagree.  The correct place for the checks should be close
to where the error is, and that is in the /calling/ code.  If the called
function is correctly written, reviewed, tested, documented and
considered "finished", why would it be appropriate to add extra code to
that in order to test and debug some completely different part of the code?
>
The place where the result of the check /really/ matters, is the calling
code.  And that is also the place where you can most easily find the
error, since the error is in the calling code, not the called function.
And it is most likely to be the code that you are working on at the time
- the called function is already written and tested.
>
And frequently check requires
computation that is done by called function as part of normal
processing, but would be extra code in the caller.
>
>
It is more likely to be the opposite in practice.
>
And for much of the time, the called function has no real practical way
to check the parameters anyway.  A function that takes a pointer
parameter - not an uncommon situation - generally has no way to check
the validity of the pointer.  It can't check that the pointer actually
points to useful source data or an appropriate place to store data.
>
All it can do is check for a null pointer, which is usually a fairly
useless thing to do (unless the specifications for the function make the
pointer optional).  After all, on most (but not all) systems you already
have a "free" null pointer check - if the caller code has screwed up and
passed a null pointer when it should not have done, the program will
quickly crash when the pointer is used for access.  Many compilers
provide a way to annotate function declarations to say that a pointer
must not be null, and can then spot at least some such errors at compile
time.  And of course the calling code will very often be passing the
address of an object in the call - since that can't be null, a check in
the function is pointless.
 
Well, in a sense pointers are easy: if you do not play nasty tricks
with casts then type checks do significant part of checking.  Of
course, pointer may be uninitialized (but compiler warnings help a lot
here), memory may be overwritten, etc.  But overwritten memory is
rather special, if you checked that content of memory is correct,
but it is overwritten after the check, then earlier check does not
help.  Anyway, main point is ensuring that pointed to data satisfies
expected conditions.
 
 
That does not match reality.  Pointers are far and away the biggest
source of errors in C code.  Use after free, buffer overflows, mixups of
who "owns" the pointer - the scope for errors is boundless.  You are
correct that type systems can catch many potential types of errors -
unfortunately, people /do/ play nasty tricks with type checks.
Conversions of pointer types are found all over the place in C
programming, especially conversions back and forth with void* pointers.

Well, I worked with gcc code.  gcc has its own garbages collector,
so there were no ownership troubles or use after free.  There were
some possibility of buffer overflows, but since most data structures
that I was using were trees or lists it was limited.  gcc did use
casts, but those were mainly between between pointer to union and
pointers to variants.  Unions had tag (at the same place in all
variants), there were accessor macros which checked that the tag
corresponds to expected variant.  It certainly took some effort to
develp the gcc infrastructure, I just benefited from it.  Earlier
versions of gcc did not have garbage collector (and probably also
did not have checking macros).

Also, you say that pointers are source of errors.  In gcc source
usualy was bad semantics, that is some function did something
else than it should.  This could manifest as a failed tag check
(IME most frequent case), segfault or wrong generated code.
And troblesome cases were the wrong code cases.

My personal codes were much smaller.  In one production case
all allocated memory was put in a linked list and freed in
bulk at end of processing.  In my embeded code I do not
use dynamic allocation.  In other case C routines are called
from garbage collected language, so most or all pointers are
"owned" by garbage collected language and C routines should
not and can not free them.  In still another cases pointer
usage follows relatively simple design pattern and is not
a problem.

You may have more tricky cases than the cases I handle using
manual memory management and can not (or do not want) use garbage
collector.  I do not know how much checking infrastructure do
you have.  Simply I reported my experience.and how I interpret
it: I may get a segfault, but segfault itself is a minor
trouble.  In particular many segfaults can be corrected almost
immediately.  Bigger trouble is when actual problem is logic
error.  In non-C coding in garbage-collected language "pointer
errors" that you mention go away, but logic errors are still
there.
 
All this means that invalid pointer parameters are very much a real
issue - but are typically impossible to check in the called function.

In gcc you could get pointer to wrong variant of a union, but called
function could detect it looking at the tag.  One could cast
a point to completely differnt type, but this would be gross
error which was rare.

The way you avoid getting errors in your pointers is being careful about
having the right data in the first place, so you only call functions
with valid parameters.  You do this by having careful control about the
ownership and lifetime of pointers, and what they point to, keeping
conventions in the names of your pointers and functions to indicate who
owns what, and so on.  And you use sanitizers and similar tools during
testing and debugging to distinguish between tests that worked by luck,
and ones that worked reliably.  (And of course you may consider other
languages than C that help you express your requirements in a clearer
manner or with better automatic checking.)

Yes, of course.

Put the same effort and due diligence into the rest of your code, and
suddenly you find your checks for other kinds of parameters in functions
are irrelevant as you are now making sure you call functions with
appropriate valid inputs.

It depends on the domain (also see below).

Once you get to more complex data structures, the possibility for the
caller to check the parameters gets steadily less realistic.
>
So now your practice of having functions "always" check their parameters
leaves the people writing calling code with a false sense of security -
usually you /don't/ check the parameters, you only ever do simple checks
that that called could (and should!) do if they were realistic.  You've
got the maintenance and cognitive overload of extra source code for your
various "asserts" and other check, regardless of any run-time costs
(which are often irrelevant, but occasionally very important).
>
>
You will note that much of this - for both sides of the argument - uses
words like "often", "generally" or "frequently".  It is important to
appreciate that programming spans a very wide range of situations, and I
don't want to be too categorical about things.  I have already said
there are situations when parameter checking in called functions can
make sense.  I've no doubt that for some people and some types of
coding, such cases are a lot more common than what I see in my coding.
>
Note also that when you can use tools to automate checks, such as
"sanitize" options in compilers or different languages that have more
in-built checks, the balance differs.  You will generally pay a run-time
cost for those checks, but you don't have the same kind of source-level
costs - your code is still clean, clear, and amenable to correctness
checking, without hiding the functionality of the code in a mass of
unnecessary explicit checks.  This is particularly good for debugging,
and the run-time costs might not be important.  (But if run-time costs
are not important, there's a good chance that C is not the best language
to be using in the first place.)
 
Our experience differs.  As a silly example consider a parser
which produces parse tree.  Caller is supposed to pass syntactically
correct string as an argument.  However, checking syntactic corretnetness
requires almost the same effort as producing parse tree, so it
ususal that parser both checks correctness and produces the result.
 
The trick here is to avoid producing a syntactically invalid string in
the first place.  Solve the issue at the point where there is a mistake
in the code!
 
(If you are talking about a string that comes from outside the code in
some way, then of course you need to check it - and if that is most
conveniently done during the rest of parsing, then that is fair enough.)

Imagne about 1000 modules containing about 15000 functions.  The
modules for a library and any exportd function (about 7000) is
potentially user-accessible.  Function transform data and do not
know where their argument came from: user or other library
function.  Processing in principle is quite well defined, so
one could formulate validity conditions for inputs and outputs.
But the conditions do no compose in a simple way.  More precisly,
in many cases when given function received correct data and is
doing right thing, then all functions it calls will receive
correct arguments.  But trouble is, what if the function is
wrong?  Natural answer: write correct code solves nothing.
Of course, one makes effort to write correct code, but bugs
still appear.  So, there are internal checks.  And failing
check frequently is in called function, because it can
detect error.  Of course, if detecting error in caller
were easy, the caller would do the check.  But frequently
it is not easy.  Look at partially made up example.
We have a mathematical problem that could be transformed to
solving linear equations.  In general, a system of linear
equations may have no solution.  But one may be able to
prove that that equations coming from a specific problem
are always solvable.  So we write a routine that transforms
input into a system of linear equations.  Equation solver
returns information if system is solvable and in case of
solvable system also description of solutions.  Taking
literaly your advice, we would just access solutions
(we proved that system is solvable so solutions must be
there!).  But in system I use and develop as written
one can not "just access solutions" without first checking
(explicitely or implicitely) return value for possibility
of no solution.  And what happens when there is no solution?
Implicit check will signal error and if check is explicit
the only sensible thing to do is also signaling error.
My point here that there is natural place to put extra
check.  If the check fails you know that there is a bug
(or possibly the input data was wrong).  And if there is
a bug that is the earliest practical place to discover it.

BTW: While I did not give complete example, this is frequent
approach to solving math problem.

I have computations that are quite different than parsing but
in some cases share the same characteristic: checking correctness of
arguments requires complex computation similar to producing
actual result.  More freqently, called routine can check various
invariants which with high probablity can detect errors.  Doing
the same check in caller is inpractical.
 
I think you are misunderstanding me - maybe I have been unclear.  I am
saying that it is the /caller's/ responsibility to make sure that the
parameters it passes are correct, not the /callee's/ responsibility.
That does not mean that the caller has to add checks to get the
parameters right - it means the caller has to use correct parameters.
 
In this sense I agree.  Simply life shows that checks are needed
and there are frequently natural places to put checks.  And frequently
those natural places are far from origin of the data.

Think of this like walking near a cliff-edge.  Checking parameters
before the call is like having a barrier at the edge of the cliff.  My
recommendation is that you know where the cliff edge is, and don't walk
there.

That is easy case.  The worst problems are ones where you do not
know that there is cliff edge.  With real cliff edge once you fall
the trouble will be obvious (either to you or to people who find you).
In programming you may be getting wrong results and do not know
this possibly making problem worse.  I simply advocate early
detection of troubles.

--
                              Waldek Hebisch

Date Sujet#  Auteur
31 Oct 24 * else ladders practice255fir
31 Oct 24 +* Re: else ladders practice9Anton Shepelev
31 Oct 24 i+- Re: else ladders practice1fir
31 Oct 24 i`* Re: else ladders practice7James Kuyper
1 Nov 24 i `* Re: else ladders practice6David Brown
2 Nov 24 i  +* Re: else ladders practice2James Kuyper
2 Nov 24 i  i`- Re: else ladders practice1David Brown
2 Nov 24 i  `* Re: else ladders practice3fir
2 Nov 24 i   +- Re: else ladders practice1David Brown
2 Nov 24 i   `- Re: else ladders practice1James Kuyper
31 Oct 24 +* Re: else ladders practice5Richard Harnden
31 Oct 24 i+* Re: else ladders practice3fir
31 Oct 24 ii`* Re: else ladders practice2fir
31 Oct 24 ii `- Re: else ladders practice1fir
31 Oct 24 i`- Re: else ladders practice1Bonita Montero
31 Oct 24 +* Re: else ladders practice22Dan Purgert
31 Oct 24 i+* Re: else ladders practice3fir
31 Oct 24 ii`* Re: else ladders practice2Dan Purgert
31 Oct 24 ii `- Re: else ladders practice1fir
16 Nov 24 i`* Re: else ladders practice18Stefan Ram
16 Nov 24 i +* Re: else ladders practice5Bart
16 Nov 24 i i`* Re: else ladders practice4David Brown
19 Nov 24 i i `* Re: else ladders practice3Janis Papanagnou
19 Nov 24 i i  +- Re: else ladders practice1David Brown
19 Nov 24 i i  `- Re: else ladders practice1Michael S
16 Nov 24 i +* Re: else ladders practice3James Kuyper
19 Nov 24 i i`* Re: else ladders practice2Janis Papanagnou
30 Nov 24 i i `- Re: else ladders practice1Tim Rentsch
16 Nov 24 i +* Re: else ladders practice2Lew Pitcher
17 Nov 24 i i`- Re: else ladders practice1Tim Rentsch
20 Nov 24 i +* Re: else ladders practice3Dan Purgert
30 Nov 24 i i`* Re: else ladders practice2Rosario19
5 Dec 24 i i `- Re: else ladders practice1Dan Purgert
1 Dec 24 i `* Re: else ladders practice4Waldek Hebisch
1 Dec 24 i  `* Re: else ladders practice3Janis Papanagnou
1 Dec 24 i   `* Re: else ladders practice2Waldek Hebisch
2 Dec 24 i    `- Re: else ladders practice1Janis Papanagnou
31 Oct 24 +- Re: else ladders practice1Janis Papanagnou
31 Oct 24 `* Re: else ladders practice217Bart
1 Nov 24  `* Re: else ladders practice216fir
1 Nov 24   +* Re: else ladders practice198Bart
1 Nov 24   i+* Re: else ladders practice196fir
1 Nov 24   ii`* Re: else ladders practice195Bart
1 Nov 24   ii `* Re: else ladders practice194fir
1 Nov 24   ii  `* Re: else ladders practice193fir
1 Nov 24   ii   `* Re: else ladders practice192Bart
1 Nov 24   ii    `* Re: else ladders practice191David Brown
1 Nov 24   ii     `* Re: else ladders practice190Bart
1 Nov 24   ii      `* Re: else ladders practice189David Brown
1 Nov 24   ii       `* Re: else ladders practice188Bart
2 Nov 24   ii        `* Re: else ladders practice187David Brown
2 Nov 24   ii         `* Re: else ladders practice186Bart
2 Nov 24   ii          +- Re: else ladders practice1Tim Rentsch
3 Nov 24   ii          +* Re: else ladders practice4fir
3 Nov 24   ii          i`* Re: else ladders practice3Bart
3 Nov 24   ii          i `* Re: else ladders practice2fir
3 Nov 24   ii          i  `- Re: else ladders practice1fir
3 Nov 24   ii          +* Re: else ladders practice4fir
3 Nov 24   ii          i`* Re: else ladders practice3Bart
3 Nov 24   ii          i `* Re: else ladders practice2fir
3 Nov 24   ii          i  `- Re: else ladders practice1fir
3 Nov 24   ii          +* Re: else ladders practice35David Brown
3 Nov 24   ii          i+- Re: else ladders practice1Kaz Kylheku
3 Nov 24   ii          i+* Re: else ladders practice23Bart
4 Nov 24   ii          ii+* Re: else ladders practice21David Brown
4 Nov 24   ii          iii`* Re: else ladders practice20Bart
4 Nov 24   ii          iii +* Re: else ladders practice2David Brown
5 Nov 24   ii          iii i`- Re: else ladders practice1Bart
4 Nov 24   ii          iii `* Re: else ladders practice17David Brown
5 Nov 24   ii          iii  +* Re: else ladders practice2Bart
5 Nov 24   ii          iii  i`- Re: else ladders practice1David Brown
6 Nov 24   ii          iii  +* Re: else ladders practice5Bart
6 Nov 24   ii          iii  i`* Re: else ladders practice4David Brown
6 Nov 24   ii          iii  i `* Re: else ladders practice3Bart
7 Nov 24   ii          iii  i  `* Re: else ladders practice2David Brown
7 Nov 24   ii          iii  i   `- Re: else ladders practice1Bart
9 Nov 24   ii          iii  `* Re: else ladders practice9Janis Papanagnou
9 Nov 24   ii          iii   `* Re: else ladders practice8David Brown
10 Nov 24   ii          iii    `* Re: else ladders practice7Janis Papanagnou
10 Nov 24   ii          iii     `* Re: else ladders practice6David Brown
19 Nov 24   ii          iii      `* Re: else ladders practice5Janis Papanagnou
19 Nov 24   ii          iii       `* Re: else ladders practice4David Brown
19 Nov 24   ii          iii        `* Re: else ladders practice3Janis Papanagnou
19 Nov 24   ii          iii         `* Re: else ladders practice2David Brown
20 Nov 24   ii          iii          `- Re: else ladders practice1Janis Papanagnou
9 Nov 24   ii          ii`- Re: else ladders practice1Janis Papanagnou
8 Nov 24   ii          i+* Re: else ladders practice9Janis Papanagnou
8 Nov 24   ii          ii+* Re: else ladders practice4David Brown
9 Nov 24   ii          iii`* Re: else ladders practice3Janis Papanagnou
9 Nov 24   ii          iii `* Re: else ladders practice2David Brown
10 Nov 24   ii          iii  `- Re: else ladders practice1Janis Papanagnou
8 Nov 24   ii          ii`* Re: else ladders practice4Bart
9 Nov 24   ii          ii `* Re: else ladders practice3Janis Papanagnou
9 Nov 24   ii          ii  `* Re: else ladders practice2Bart
10 Nov 24   ii          ii   `- Re: else ladders practice1Janis Papanagnou
8 Nov 24   ii          i`- Re: else ladders practice1Bart
5 Nov 24   ii          `* Re: else ladders practice141Waldek Hebisch
5 Nov 24   ii           +- Re: else ladders practice1fir
5 Nov 24   ii           +* Re: else ladders practice24David Brown
5 Nov 24   ii           i+* Re: else ladders practice17Waldek Hebisch
5 Nov 24   ii           ii`* Re: else ladders practice16David Brown
5 Nov 24   ii           i`* Re: else ladders practice6Bart
5 Nov 24   ii           `* Re: else ladders practice115Bart
1 Nov 24   i`- Re: else ladders practice1fir
2 Nov 24   `* Re: else ladders practice17Tim Rentsch

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal