How do you debug?

W

werasm

When I write code I use a lot of:

std::cout << "TEST1\n";

...
...
<some code>
...
...

std::cout << "TEST2\n";

etc.

But is there some better way do this kind of debugging (maybe with some
preprocessor commands)?

I know that I could use the gdb debugger but often I prefer the above
procedure.

I usually write a little piece of code, test it, then integrate it.
The code is written in a way that makes it easily integrable. To
achieve
this I often use either callback functions or interfaces, depending
on circumstance. For testing I often implement the interfaces by
logging
to std::cout, yes.

After integration I test again. For this the implementation of the
interfaces
log to a low priority task (to impose as little as possible runtime
overhead).
Logging can be switched on/off remotely on a per class basis, but the
class
has to derive from something that I call a DiagnosticSubscriber. This
mechanism is quite handy when debugging multi-threaded applications.

I very rarely use the debugger nowadays. When tests fail I usually
think
about why they fail by using a pen and paper first. I have used
debuggers
in the past though. One such case I was programming in a team, and
after
I added my code, the application crashed for no apparent reason.
After
debugging I realized that the size of the image caused someone else's
stray pointer to overwrite my code (The debugger just showed me the
point
of the crash, and that there was nothing wrong with the code itself).
The culprit was not found by the debugger, though. It was found by
inspection on a mass scale.
 
P

Pavel Lepin

Puppet_Sock said:
Puppet_Sock a écrit :
On Oct 2, 4:56 am, Michael DOUBEZ
[snip]
Actually, keeping asserts in the release code (i.e.
not using NDEBUG) is a good idea; just like wearing a
safety belt after you have learned how to drive.
You will find a lot of people who disagree with that.
Certainly there are many situations where it is just
unacceptable.

I work on an aeronautic embedded system with real time
and fault tolerant cobstraints. It is pretty critical and
I can tell you the asserts are still in the code when it
takes off.

I'm a nuke. If one of the control computers did an
assert, the operator would come and find me. This
would not end well.

I don't think you mean the same thing by "assert"
that I do. When a program hits an assert and fails,
the program stops. All over, bang, goodbye, only
way to get it back is to restart the program.

This is something you put in your aircraft?

Disclaimer: I've never worked on life-critical applications.
But I believe it would be better for the avionics suite to
shut down if an assert fails than to execute the code
outside of parameters it was designed for. For all you know
it might decide to fly a jumbo jet through a barrel roll,
or flush fuel tanks, or depressurise the passenger's
compartment. It's better for the software to honestly admit
to its human operators that it has encountered something it
cannot handle and has to give up, than try to cover it up
working in conditions it was never ever meant for. Humans
trust their computers. When they shouldn't, we gotta tell
them so.

A brief googling/wikiing failed to find a convincing case.
The following page:

http://www.cs.tau.ac.il/~nachumd/verify/horror.html

....seems to describe something close to what I'm talking
about.

"16. An airplane software control returned inappropriate
responses to pilot inquiries during abnormal flight
conditions."

Unfortunately, the link to details is broken, so it's hardly
a convincing piece of evidence.
 
J

James Kanze

James said:
[snip]
Actually, keeping asserts in the release code (i.e. not
using NDEBUG) is a good idea; just like wearing a safety
belt after you have learned how to drive.
You will find a lot of people who disagree with that.
You'll also find a lot of people who think that the world is
flat.
Really? I never found one. :)

Question of milieu. If you frequent a milieu where geography or
astronomy are unknown, you'll find them. If you frequent a
milieu where software engineering is unknown, you'll find people
who believe you should take asserts out of deliverable code:).
One fundamental question is whether there is a notion of
"correctness" for the behavior of the program. Whenever
correctness of the results matter, I would hope that asserts
are left in so that in case of a bug that causes the state of
the program to be unforseen (and therefore potentially bogus)
there is a chance that it will crash. Few things are worse
than output that is believed to be correct but isn't; that can
be very costly, too.
Compilers are an example: I prefer a compiler crash to the
generation of potentially faulty object code any day.
On the other hand, there are programs where correctness is not
that meaningful a concept. Think of a game. The physics engine
may sometimes not detect that two objects are at the same
place at the same time or the rendering may be a little off
due to rounding errors or arithmetic overflows. Now, those
effects might be gone after two or three frames and as long as
the user experience is good, there is a reason to prefer the
game going on to the game crashing. In that case, it could be
a correct business decision to eliminate the asserts in
release code.

I'll admit that games are a special case with regards to
software engineering, and obey very different rules. There are
probably also a few other cases, that I'm not familiar with
either. But you've doubtlessly seen enough of my postings to
know my predilection for hyperbole (which I alternate with
typically gallic litote to really confuse people).
 
J

James Kanze

[...]
My understanding is that is not the topic here, we are talking about
asserts in pre an post conditions or invariants and check points.

I think that's a good point. We're talking about the detection
of programming errors. But the real point is simply this: can
you handle the error. If you can, then you don't use
assert---even in debug mode. You use something else, like
exceptions. And you write test cases which trigger it, so you
can verify that you do handle it correctly.

And if you can't handle it, of course, just ignoring it is NOT
really an option. You have to abort.
 
J

James Kanze

Puppet_Sock a écrit :
[snip]
Actually, keeping asserts in the release code (i.e. not using NDEBUG) is
a good idea; just like wearing a safety belt after you have learned how
to drive.
You will find a lot of people who disagree with that.
Certainly there are many situations where it is just
unacceptable.
I work on an aeronautic embedded system with real time and
fault tolerant cobstraints. It is pretty critical and I can
tell you the asserts are still in the code when it takes
off.
I'm a nuke. If one of the control computers did an
assert, the operator would come and find me. This
would not end well.

You mean he would prefer you to stumble on, not knowing the
internal state of the program, and behave in an undefined
manner, maybe causing a nuclear meltdown.

The very first rule in all critical systems is if there is the
slightest doubt about the program, abort and get the heck out of
there, so that the redundant back-up systems can take over.
I don't think you mean the same thing by "assert"
that I do. When a program hits an assert and fails,
the program stops. All over, bang, goodbye, only
way to get it back is to restart the program.
This is something you put in your aircraft?

It's certainly something that is in the control systems on an
Airbus (or was when I consulted there, in the late 1970's). It
was a contractual requirement when I did a locomotive brake
system, in the mid 1980's---in fact, any time there was any
doubt concerning the reliability of the system, they cut the
power supply to it.

[...]
I'm just guessing, but what I'm guessing is that you are
a bigtime Unix coder.

Which "you"? I've worked on many different types of systems,
from 8 bit embedded processors with 2 KBytes ROM, to IBM
mainframes.
You step through your code to catch stupid mistakes.

Except that stepping through the code doesn't necessarily catch
all, or even most stupid mistakes. You use code review to catch
stupid (and not so stupid) mistakes. And you use extensive
tests to catch problems in your code review process.
I've seen this lots of times where guys put code back into the
codebase without ever stepping through it.

In most places I've worked, at least since the late 1980's, the
version control system was set up so that you couldn't check in
code without it having passed its unit tests. And the unit
tests were reviewed, along with the code, to ensure coverage.
In some places, at least, checked-in code was quarentined until
someone cleared it, ensuring that it had passed code review.

The review process is critical. At least some of the reviewers
must be relatively unfamiliar with your code, to bring a fresh
view of it. Nothing you, or anyone who worked closely with you
during the development phase, can do will replace this.

[...]
I've also had the case where the coder refused to believe
there was anything wrong with his code till I fired it
up in the debugger and showed him the bad behaviour.

If the code review panel says that the code is wrong, it is
wrong. The programmer either fixes it, or is fired.
 

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

Forum statistics

Threads
474,270
Messages
2,571,353
Members
48,038
Latest member
HunterDela

Latest Threads

Top