Is goto Still Considered Harmful?

A

Andrew Cooper

Not always. There exist these things called unconditional branches,
which are 100% taken. Wink!

That's all well and good, and of very little help.

The purpose of a branch predictor is not to identify whether a specific
branch is taken or not. The purpose of a branch predictor is to feed
the most likely new instruction pointer back into the instruction fetch,
which also involves making a guess as to whether the branch is going to.

But this is dangerously off topic...

~Andrew
 
K

Kaz Kylheku

That's all well and good, and of very little help.

The purpose of a branch predictor is not to identify whether a specific
branch is taken or not. The purpose of a branch predictor is to feed
the most likely new instruction pointer back into the instruction fetch,
which also involves making a guess as to whether the branch is going to.

And the 100% likely instruction following an unconditional branch is ...
 
A

Andrew Cooper

And the 100% likely instruction following an unconditional branch is ...

How do you expect the knowledge that a branch is certainly taken to help
you know where the branch goes to?
 
L

Les Cargill

Jos said:
In your dreams, perhaps.

...

So gotos are efficient in machine code, but the
discussion wasn't about efficient machine code.

The problem with gotos is that they break the ... symmetry of
if.. then...else trees. They are "blue wires". That means it's
perceived to be a hack.

That, and that grad students who grade labs can grep for them.

Using gotos to implement state logic means you're not really
in the land of if...then...else trees any more.
...

No, you can still avoid them completely (although
there's no need to goto such an extreme effort..)
And of course keeping things functional will always
pay off!


Functional is great if you can trust it and you're not
dependent on pseudo-emergent side effects.

Still, Lisp has been described as "fingernail clippings
in oatmeal."
 
W

wilson

First of all, this actually's no issue restricted to a GOTO.
Everytime you do sometking like

if ( some_condition )
do_A( );
do_B( );

there's an obvious problem (at least if this has been written
under the assumption that do_B() would only be invoked in case
that 'some_condition' is true) - how bad the results are depends
on what the do_B() call does.

In some cases it might help to religiously enclose IF blocks in
curly braces to make such problems stand out more. E.g.

if ( some_condition ) {
do_A( );
}
do_B( );

may be more visible (but that always requires that someone is
actually looking at this code and starts wondering what's going
on).

The "Pythonistats" had their day, claiming that it never would
have happened to them due to to the relevance of white-space in
Python. I'm not convinced, I think it could have happened even
more easily in Python (given they had a GOTO statement) since
an editor can't even know when to indent.

With a reasonable editor (or a indentation tool) this flaw
could easily have been exposed to anyone taking jist a super-
ficial glance, i.e., if some rather easy to understand code
like this (after proper indentation)

if ( some_condition )
goto fail;
goto fail;
if ( some_other_condition )
goto fail;

doesn't raise an alarm bell what ever will? And the whole layout
of the code isn't very convincing:

if ((err = SSLFreeBuffer(&hashCtx)) != 0)
goto fail;
if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0)
goto fail;
if ((err = SSLHashSHA1.update(&hashCtx &clientRandom)) != 0)
goto fail;
goto fail;

Why not make it more easy to read like e.g.

if ( ( err = SSLFreeBuffer( &hashCtx ) )
|| ( err = ReadyHash( &SSLHashSHA1, &hashCtx ) )
|| ( err = SSLHashSHA1.update( &hashCtx &clientRandom ) ) )
goto fail;

(I'd also put a comment in front of that, trying to expalin
what that's supposed to check.)

The only thing I can see here is another example of "don't
repeat yourself" - if you have to write "goto fail;" many
times in a row something is fishy, someone just mechani-
cally copy-and-past-ed without giving it a thought...

I guess the only way to avoid such things is to indent code cor-
rectly (using all tools available) and looking out for anything
that doesn't look right on first sight.

And when it comes to Dykstra's "Goto considered harmful" this
seems to be really far-fetched. The paper is from 1968 (nearly
50 yeares ago) and times and programming practices were quite
different back then (quite before my time;-). While I'd comple-
tely agree that something like (and I guess that's something
akin to what Dykstra actually was ranting about)

GOTO i 237, 384, 293, 204, 381, 493, 1002, 536, 785, 662

- as could and would be done in FORTRAN (I've seen code like
this and was unlucky enough to have to try to unravel it) - is
definitely "harmful", but that's nothing anybody in a sane
state of mind would do in a modern computer language (unless
for an obfuscation contest). But that bears no relationship to
some simple and straightforward GOTOs in otherwise sane code.

Regards, Jens


My two cents for whatever it is worth.

Of all the suggestions, I like this use of logical "or"s the best.

It makes it clear exactly what is happening.
And with a compileer that exits the checking of the Boolean as soon as if
finds a negative value (almost all compilers today) it is as fast as the
original version.
The result: clarity and speed.
 
W

Wolfgang Kilian


Nobody mentioned exception handling, yet?

If goto is useful in a language, it is a sign that the language is
lacking exceptions as a concept. Error conditions and breaking out of a
loop are covered by

try ... raise EXC ... catch EXC ...

or similar, if the language supports it. While the control flow is the
same, it expresses the intention of the programmer. Also, it doesn't
permit control flow to accidentally reach the 'catch' part, which is
another common error.

(Exceptions have an issue with properly cleaning up, but that is the
same with explicit goto.)

-- Wolfgang
 
W

wilson

My two cents for whatever it is worth.

Of all the suggestions, I like this use of logical "or"s the best.

It makes it clear exactly what is happening.
And with a compileer that exits the checking of the Boolean as soon as
if finds a negative value (almost all compilers today) it is as fast as
the original version.
The result: clarity and speed.


Sorry. That last lines hould have read the program exits checking the
Boolean as soon as it finds a true condition. A false consditon sends it
on to check the next conditon. Again, almost all current cvompilelrs skip
checking the rest of the Boolean as soon as possible.

My only excuse is that it is late at night.
 
J

Johannes Bauer

He also invented semaphores, which are the worst synchronization primitive
ever: and, ironicaly, can be considered to be "the goto of synchronization".

Although widely off-topic, I find this statement curious. Contrary to
you, I think semaphores are a great improvement over code that uses
mutexes and condition variables (which I would agree are the "goto of
synchronization") and yet they're small enough for deeply embedded
environments (where monitors or other fancy stuff is not feasible). Plus
they're really easy to understand ("counter").

Why the dislike of semaphores? Not looking for a flame here, but just
really trying to understand where you're coming from.

Cheers,
Joe

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
D

David Brown

And the 100% likely instruction following an unconditional branch is ...

You are missing the point. Modern cpus pre-fetch instructions before
they are executed - the branch predictor is part of that, as it
determines which instructions to pre-fetch. By default, the system will
pre-fetch instructions at increasing address - an unconditional branch
breaks that flow and means the pre-fetcher must change course. So while
an unconditional branch will never be mis-predicted, it still needs to
be predicted and handled by the branch predictor, the branch target
buffer, and the pre-fetch buffer.

(Exact names of these parts, and how they are split up, will of course
vary between processor implementations - but I hope you get the idea.)
 
D

David Brown

Yes it is frowned upon and it is bad practice. But I'd prefer that a
language still has it just in case (many don't; C does, otherwise I
wouldn't
be here - I need it for auto-generated code).

But the code error in the article was about how code blocks are delimited:

if (a)
b;
c;
if (d) ...

Statements b and c are both indented and look at first glance as though
they
belong to the preceding if-condition, but c (which happened to be a goto)
was always executed.

Insisting that all statement sequences have {...} braces, even when
there is
only one statement, I think would have helped. (Also having statements
require a matching closing delimiter, but C uses {...} braces for
everything.)

As it is, it is common for a statement such as c to not have a } to close
it, so it's easier to miss the bug.

That was my first thought too. I stick to two forms of conditional:

if (a) b;

and

if (a) {
b;
}

I only use the first form if "b" is simple, there is no "else", and
there are no doubts that it is a single statement. Examples are simple
assignment, return statements, and (though I seldom use them) goto's.
Otherwise I insist on brackets.
 
D

David Brown

What really puzzles me about this bug is that pretty much all C/C++
compilers for large systems (and certainly GCC), will issue an
"unreachable code" warning at all but the minimal warning level. At
least around here the policy is compile at a high warning level, and
treat warnings as errors, not doing something like that, especially in
security critical code, just seems sloppy.

Now it would be impossible to detect all cases of unreachable code,
but a simple case like this should be trivial.

Good point.

One wonders what other errors could be found by a simple "-O2 -Wall",
never mind "-Wextra".
 
K

Kenny McCormack

Sorry. That last lines hould have read the program exits checking the
Boolean as soon as it finds a true condition. A false consditon sends
it on to check the next conditon. Again, almost all current cvompilelrs
skip checking the rest of the Boolean as soon as possible.
[/QUOTE]
One would hope that ALL compilers make || and && a short-circuit
evaluation as it is REQUIRED to be by the standard, and has been since K&R.

Indeed. One wonders two things:

1) Why the previous poster thought that the functionality was optional.
(And that "almost all" compilers do it this way)

2) Why roving gangs of regs haven't pounced on this already.

P.S. There is exactly one language that I know of, that uses && and ||, for
"and" and "or", respectively, that doesn't implement the so-called "short
circuit" evaluation. That language is "WinBatch" (www.winbatch.com).
 
M

mark.bluemel

Is goto Still Considered Harmful?

In my hands, yes. Mind you, I'm also at risk with kitchen knives.

My first programming job was using COBOL-68. In-house standards led to label
names like "C-100", "CA-100", "CAA-100", "CB-100" and so on. It was all to easy
to branch to the wrong one, so I stopped using GOTO and wrote GOTO-less code in
COBOL for about 7 years.

I currently mainly code in Java which has no "goto", and don't feel the lack.

When coding in C, I would consider using goto for error exits, perhaps, but otherwise try to avoid them.

--
Mark
"Any reference to 'goto' (an obscure Japanese admiral) are obscene, unfit for
your eyes and anyway don't mean what you think they do" - University of
Nottingham Maths department addendum to the Algol manual, circa 1975,
paraphrased.
 
T

Thomas Koenig

Stefan Ram said:
Is GOTO still considered harmful?

The most elegant control flow statement has to be the
AT statement (equivalent to COME FROM).

Consider the beauty of

K = 3
20 I = K

and, somewhere quite far from this,

AT 20
K = 5
END

which sets K (and, in consequence I) to 5 but only when a
debug option is set.

Remove debugging, and your program does something quite different.

This was already in the Fortran G compiler, so it must be good ;-)
 
Q

Qolin

"Thomas Koenig" wrote in message
The most elegant control flow statement has to be the
AT statement (equivalent to COME FROM).

Consider the beauty of

K = 3
20 I = K

and, somewhere quite far from this,

AT 20
K = 5
END

which sets K (and, in consequence I) to 5 but only when a
debug option is set.

Remove debugging, and your program does something quite different.

This was already in the Fortran G compiler, so it must be good ;-)

Reminds me of the COMEFROM statement...

Qolin
 
T

Terence

There is a related question:
Is "Come From" still considered harmful?

This was the subject of a new article in the 1970's, upon which my M.Sc.
thesis professor asked for my comments.
I replied it was a humerous (non-serious?) response to the other
above-referenced publicaction.
I also explained how it could be implemented.

(I still got a 94% average). :eek:)>
 
S

Stefan Ram

Thomas Koenig said:
Remove debugging, and your program does something quite different.

In Java,

boolean var = false;
assert var = true;
if( var )...

does something quite different, when the program is being executed
with »java -enableassertions«.
 
G

glen herrmannsfeldt

In comp.lang.c Qolin said:
"Thomas Koenig" wrote in message

I did use the compiler, but I never tried this feature.
As well as I know it, you are supposed to use it, for example, to
print out values of variables, not change them.

Under "Programming Considerations:"

"3. An error in a program should not be corrected within a debug
packet; when the packet is removed, the error remains in the
progran."

There is a DISPLAY statement, which generates output similar to
NAMELIST, but without the need for a separate NAMELIST statement.
(Why didn't that ever make it in to the standard?) As far as I can
tell, DISPLAY can only appear in a DEBUG packet.

Seems that the idea is to put all debugging statements in one
place (just before END) making it easier to remove when the buts
are fixed.

DEC instead used a feature where lines starting with D were
comments, except when a compiler debugging option was used.
One should be able to quickly search for, and remove, such lines
once debugging was done.
es which sets K (and, in consequence I) to 5 but only when a
Reminds me of the COMEFROM statement...

Stories are that COMEFROM was once added to a PL/I compiler, I
don't know about any Fortran compilers.

Especially interesting for Fortran would be the computed COMEFROM
statement.

-- glen
 
K

Kaz Kylheku

In Java,

boolean var = false;
assert var = true;
if( var )...

Why bring up Java; we have that in C:

assert (var = true); /* doesn't happen if NDEBUG is on */
 
J

James Van Buskirk

Why bring up Java; we have that in C:
assert (var = true); /* doesn't happen if NDEBUG is on */

At last! A C programmer to inflict the Question on! Now, what if
true is a const _Bool with internal representation B'00000010'
and var is also an _Bool. Does the assert happen if NDEBUG is not
on?
 

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
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top