Debugging standard C library routines

C

CBFalconer

R

Richard Heathfield

Eric Sosman said:
This programmer you describe seems a bit of an odd fish. He's
reckless enough to ignore warning messages, yet diligent enough to
initialize all his pointers. Sounds like a person with a multiple
personality disorder ...

Well, of course what we're really talking about is "what constitutes good
practice?" What kind of code is easiest to debug? What kind of strategy
works best for dealing with diagnostic messages? Do we strive for a clean
compile at all costs? I used to do so, but I found that sometimes I
couldn't /get/ a clean compile without adding spurious casts to the code,
which I was loathe to do. So we have to consider a strategy on how to deal
with warnings. When is a warning significant? To me, the answer is "it's
significant for as long as you can't understand why it's there". So - if a
compiler told me "hey, you might be using this thing before giving it a
proper value", then yes, I'd take it seriously. Unfortunately, it is not a
panacea (and yet it certainly looks like one). It can't, for example, deal
with foo(&obj); - and so now you have the worst of both worlds - no
diagnostic message AND no initialisation. Oopsie.
It's interesting to read this in light of remarks about "drool-
proof languages" on another current thread ...

Yes, I'm trying hard to avoid quoting Sturgeon's Law here...
I feel -- without quantitative evidence, I admit -- that there's
more to be gained from improving a programmer's skills than by trying
to compensate for his deficiencies.

I'm sticking my neck out here, but I am willing to bet any amount up to and
including a penny that you spend hardly any time debugging your own code.
Not *no* time, but hardly any time. I suspect that you make a low number of
mistakes, and that most of those you do make are fixed within seconds or,
at most, minutes of your seeing their symptoms emerge for the first time.
It's certainly true for me, anyway, and I'd be surprised if it weren't true
for you too. And the reason is obvious - you know what you're doing, and
you've evolved a strategy for successful code development that *works* -
for you. And I've evolved a strategy that works for me. There's nothing in
the rules says we have to have evolved the /same/ strategy. And maybe
that's why we're arguing. :)

Now, when I have to debug someone else's code, that can take a bit longer,
because they didn't write it the way I would have wanted them to write it.
When debugging other people's code, then, and given the choice, I'd rather
chase a stable target than a Heisenbug. So I recommend to people that they
write the code in a way that makes it easy for /me/ to debug it. (After
all, that's probably what I'll end up doing anyway!)
Get rid of the STOP sign at the busy intersection, but make sure
that anyone who fails to stop *will* be run over by a cement truck.

Yes, absolutely. In a computer, nobody gets hurt (at least, not during
initial program development!) - we can run the little variables up to the
stop sign over and over again, and watch them go over the line and get
crushed by the truck over and over, and eventually we figure there's
something wrong with their brakes. So we go fix that. Typically, it takes a
few seconds, half of which are spent recovering from slapping our own heads
- "DUH!" - as we marvel at how we could have been so dumb.
 
R

Richard Heathfield

Ian Collins said:
Thank goodness C99 gave us the ability to declare variables at point of
use, this entire debate becomes moot.

Only when C99 becomes widely implemented.
 
R

Richard Heathfield

Christopher Layne said:
Yes. But is that really a good enough reason to say "always initialize
every pointer and tie your shoes before going outdoors?" Might as well
never use malloc and always use calloc while we're at it.

If calloc guaranteed to initialise objects to their static default
initialiser values, then I would indeed use it. But it doesn't. In fact, it
can't. So you have to put in the explicit assignment code yourself. No
getting around it. :-(
I pretty much agree - but after a certain point where it reaches
compulsiveness, then it starts to head into doubting something you already
know or have enough experience with that pre-initializing ends up being
token exercise.

I think of it as "defence in depth", and I've found it to be a valuable
strategy over the years. I have twice been bitten by failing to follow it
(in each case, no compiler diagnostic message would have helped me, since
the first use of the object in each case was to pass its address to another
routine). In each case, the bug was only discovered in production. I'm not
prepared to risk a third such occasion.

<snip>
 
C

CBFalconer

Ian said:
Richard Heathfield wrote:
.... snip about preinitializing everything ...
Thank goodness C99 gave us the ability to declare variables at
point of use, this entire debate becomes moot.

On the contrary, to my mind this simply opens up another area in
which to foul things. In particular such declarations are
inordinately sensitive to goto to points within the block. Without
initialization, this problem goes away.

I don't buy the argument that goto should never be used. I do
agree that general use in place of structured constructs leads to
spaghetti code. The rarer such use becomes, the more likely the
coder will not recognize the dangers involved.

Besides, I like knowing where to find the variable declarations.
If there are too many for convenience, or the function is too long,
it is a sign that the code is mis-structured.

--
Some informative links:
< <http://www.geocities.com/nnqweb/>
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/>
 
C

Christopher Layne

CBFalconer said:
Besides, I like knowing where to find the variable declarations.
If there are too many for convenience, or the function is too long,
it is a sign that the code is mis-structured.

I personally despise this C++/"declare on a whim" style. I like to know what
I'm getting into when I read over a function - and a function which has it's
table of contents spread out and buried within individual chapters just
pisses me off more than it helps anything.
 
J

jmcgill

Christopher said:
I personally despise this C++/"declare on a whim" style.

I agree that declarations should be at the top of a block. But I remain
fond of one exception:

int k=SOME_MAX;
for( int i=0; i<k; i++ ){/* wobble */}

I only recently realized that was a non-portable extension, even though
I've been using it since, oh, forever.
 
I

Ian Collins

Christopher said:
I personally despise this C++/"declare on a whim" style. I like to know what
I'm getting into when I read over a function - and a function which has it's
table of contents spread out and buried within individual chapters just
pisses me off more than it helps anything.

Not a problem when you keep your functions down to a dozen or so lines.

I guess it depends on where you are coming form, having been a C++
developer for the past decade and a bit, I'm used to declaring variables
where they are used (and where I realise they are required!).
 
K

Kenny McCormack

This is a stupid and foolish attitude, and requires warning other
readers. I still haven't seen your apology.

I trust you are holding your breath...
 
C

CBFalconer

jmcgill said:
I agree that declarations should be at the top of a block. But I remain
fond of one exception:

int k=SOME_MAX;
for( int i=0; i<k; i++ ){/* wobble */}

I only recently realized that was a non-portable extension, even though
I've been using it since, oh, forever.

It's portable, under C99.

--
Some informative links:
< <http://www.geocities.com/nnqweb/>
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/>
 
R

Richard Heathfield

CBFalconer said:
... snip about preinitializing everything ...

On the contrary, to my mind this simply opens up another area in
which to foul things. In particular such declarations are
inordinately sensitive to goto to points within the block.

Not for people who avoid goto like the... the... like they avoid cliches.
Without initialization, this problem goes away.

You seem to be saying that, IF I adopt one particular coding practice that I
find unwise (the use of goto), AND if I adopt another particular coding
practice that I find unwise (the use of on-the-fly declarations), THEN a
practice that I find useful may become less useful. Well, perhaps. And IF I
start walking around with my eyes shut, AND changing my direction of motion
randomly, THEN I won't bother glancing right, left, and right again before
crossing, since there won't be any point. But until then...
I don't buy the argument that goto should never be used.

I have never tried to sell that argument, as far as I can recall. On the day
a goto makes my code clearer to me than a more structured approach, I'm
quite prepared to use it. Programming is about clarity, after all. But a
goto that dives back up above an uninitialised mixed declaration is even
less likely than usual to strike me as constituting a way of making the
code clearer.
 
R

Richard Heathfield

jaysome said:
And the reasons that support that argument make C90 (strictly) not
portable as well.

Sure - strictly speaking. But in practice, I can write normal C90 code -
stuff that doesn't mess around in the dark cobwebby corners of the language
- and expect it to compile just about anywhere. But just about any single
C99 feature I choose to employ could render my code non-portable. Even //
comments will cause my code to be rejected by some implementations
(including the one I use most often myself).

Almost all of the code I write nowadays falls into one of four categories:

1) I know it's for S16ILP32 Linux
2) I know it's for S16ILP32 Windows
3) I know it's for both 1) and 2) above
4) I haven't the faintest idea what it will end up on

And most tends to be in the last category. So I have to choose - what do I
consider to be the *most portable* way to write code? And as far as I can
make out, the most portable strategy is to write code in the common subset
of C90 and C99. If anyone has any better ideas, I'd love to hear them.
 
R

Richard Bos

Frederick Gotham said:
Richard Heathfield posted:


If malloc'ing less than a kilobyte, I wouldn't bother.

On a board which doesn't have the memory to run gdb? You'd better.

Richard
 
R

Richard Bos

jacob navia said:
In a debug setting is better to never check malloc, so, if there is any
failure the program crashes immediately at the point of failure.

Assuming that writing through a null pointer - on an unusual kind of
board, no less - _will always immediately_ crash is unbelievably stupid.
This is good advice. Start with KNOWN conditions.

It is bad advice. It makes you rely on the assumption that you have
determined all such pointers.

Richard
 
R

Richard Heathfield

Richard Bos said:
Assuming that writing through a null pointer - on an unusual kind of
board, no less - _will always immediately_ crash is unbelievably stupid.

The latest party line appears to be that Mr Navia isn't unbelievably stupid,
but merely not very skilled at English. It may be that he intended to say
"Whether or not in a debug setting, it is better always to check malloc;
there is no guarantee that the program will crash immediately at the point
of failure" but that he accidentally said pretty much the exact opposite.

It is bad advice. It makes you rely on the assumption that you have
determined all such pointers.

No, it isn't bad advice, and no, it doesn't make you rely on any such thing.
It merely increases your confidence that your program's behaviour is
deterministic, and makes debugging a lot easier.
 
J

jacob navia

Richard said:
Assuming that writing through a null pointer - on an unusual kind of
board, no less - _will always immediately_ crash is unbelievably stupid.

The OP is running linux. Linux has memory protection, as far
as I remember.

But better treat people of stupid immediately, specially if
its Jacob Navia...

That doesn't cost anything since the guy never gets upset...
 
J

jacob navia

Richard said:
Richard Bos said:




The latest party line appears to be that Mr Navia isn't unbelievably stupid,
but merely not very skilled at English. It may be that he intended to say
"Whether or not in a debug setting, it is better always to check malloc;
there is no guarantee that the program will crash immediately at the point
of failure" but that he accidentally said pretty much the exact opposite.

Linux supposes memory protection as far as I remember.
The OP said it was running some linux system!

jacob
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top