[comp.sys.ibm.pc] Turbo C/Pascal, debugging

paul@imsvax.UUCP (Paul Knight) (07/07/87)

n



From my buddy Ted Holden




     Some thoughts on C compilers and debugging.  First, I would have
real moral reservations concerning the possibility of buying a copy of
MicroSoft's Quick C.  Left to their own devices, Gates and Co. would go
on selling clunky C compilers for $500 or more forever.  I mean, I know
for sure how many compilers there were on earth which were actually fun
to use before Borland ( 0), and can easily guess how many there will be
after Gates has gotten rid of Borland ( Again, 0).

     The last last piece of literature I ever got from Gates was a
generous offer to allow me to spend $3000 on an OS/2 C compiler and a
chance to win a seat at one of his nifty OS/2 conferences.  I know he
didn't enjoy reading my reply.

     I regard most of the debugging systems in the mini-micro world as
jokes.  For simply seeing variable values at specific points in a
program, printf's and writeln's are faster, given something really fast like
Borland's systems.  Further, the notion of single-stepping through
real-world programs strikes me as ludicrous.  In real life, problems
often show up in the middle of some 700 line loop on the 300'th pass
through.  Only a masochist would want to single-step through that.

     The idea of a hardware debugger, such as Periscope's, is valid;  if
you need to see values of variables AFTER the system crashes, there
ain't no other way.

     What I like about Turbo Pascal, and I don't seem to be seeing these
features in Turbo C, are the checks on system errors at run time.  A
number of things which used to drive me batty using state-of-the-art
Fortran compilers on mainframes never see the light of day in Turbo
Pascal.  The following code:

program test1;
{$R+}
var

i,j,k,l,ii,jj,kk,ll:    integer;
a,b,c,d,e,f,g:          real;
aa,bb:                  array[1..5] of integer;

begin

a := 1;
b := 0.;
c := a/b;

i := 6;
aa[i] := 5;

end.


will be stopped in its tracks at runtime, and the user will be brought
back to the editor with the cursor on the offending line of code
(actually, twice).  This is tremendously useful, and I don't see it in
Turbo C or hear about it from Microsoft, although I have to believe that
Borland will have this kind of feature in Turbo C long before MicroSoft
hears about it.  I have never seen such a feature elsewhere in the
mini-micro world.


Ted Holden,
HT Enterprises


-- 
                                Paul Knight

Disclaimer:  Invaders from another sphere may be using my account.
	     Look for multiple signatures before you flame.  Thanks.

mlinar@poisson.usc.edu (Mitch Mlinar) (07/07/87)

In article <719@imsvax.UUCP> paul@imsvax.UUCP (Paul Knight) writes:
>
>
>From my buddy Ted Holden
>
>  ......
>
>     What I like about Turbo Pascal, and I don't seem to be seeing these
>features in Turbo C, are the checks on system errors at run time.  A
>number of things which used to drive me batty using state-of-the-art
>Fortran compilers on mainframes never see the light of day in Turbo

I don't argue with the fact that Turbo Pascal has more error checking than
either Turbo C or Fortran.  HOWEVER, this is more a fundamental difference
between Pascal and C and NOT just a compiler nicety.

I suggest that Ted read both Wirth's book on Pascal and K&R C before
complaining about a problem that is specifically handled by both languages.
C, in its intent to run fast and small, DOES NOT automatically perform
array bound checking, divide-by-zero test, etc.  (It is often both run-time
and compiler dependent.)  IT IS NOT PART OF THE LANGUAGE.

Ted's comments are not that far off-base, but he should consider the
language before trashing (Turbo) C as no good.  One would expect Pascal to
be better at this; after all, it was written as a teaching language -
something that C is certainly not.

-Mitch

davidr@hplsla.HP.COM ( David M. Reed) (07/08/87)

Ted, I think your last  comment is one of the main reasons I have been slow to
pick up  seriously  on C, the lack of  checking  at compile  time for  syntax,
parameters,  assignments, and other things that can so easily happen.  And one
of the reasons I particularly  like Pascal, because of its basic simplicity of
language with strong type checking, yet providing a way to organize my program
(via  functions  and  procedures).  I  realize  some of the  flexibility  (and
ultimately the power) that comes with such a "loose" language as C, but I trip
over myself so frequently  with Pascal (even  exerting great caution and care)
that I almost fear  working  with some of my big  programs in C.  (And so many
errors  are  just  simple  typos or  brain/finger  speed  coordination.)  I am
grateful for very fast  compilers  like Borland puts out, for my debug time is
GREATLY  reduced.  And I also  find  that at least  90% of the  time  the best
debugger is judiciously placed WRITELN/printf  statements (fast and effective,
especially with fast compilers like Borland's).

I am also grateful for the useful Pascal extensions that have been provided by
Borland,  whether  I need a  convenient  way to  access  the  system  or  just
manipulate strings.  The majority of my programs deal particularly with string
handling  functions, as opposed to numbers, and Microsoft Pascal, for one, is,
in my opinion,  Extremely Poor in this area (together with its very High Price
for a Very Slow  compiler)  eliminated it in the choice of a Pascal  compiler.
So far as C is  concerned,  I look  forward  to getting  my copy of Turbo C (I
currently use Lattice C when I do C, as I did not care for Microsoft C).

Now  don't get me  wrong.  I am not  against  MicroSoft.  Just  because I also
chose  DESQview  over MS Windows  (because I found it easier to learn and use,
and  more  productive  because  I can run LAN  and  modem  communications  and
compiles and other active  programs in the background so easily when used with
my AST RAMpage card).  And I chose another editor over MS Word, and....

greg@gryphon.CTS.COM (Greg Laskin) (07/10/87)

In article <719@imsvax.UUCP> Ted Holden writes:

>     I regard most of the debugging systems in the mini-micro world as
>jokes.  For simply seeing variable values at specific points in a
>program, printf's and writeln's are faster, given something really fast like
>Borland's systems.  Further, the notion of single-stepping through
>real-world programs strikes me as ludicrous.  In real life, problems
>often show up in the middle of some 700 line loop on the 300'th pass
>through.  Only a masochist would want to single-step through that.

This is a matter of taste and experience.  In real life, most of the
bugs in C programs that I've been called upon to fix involve
unintented and sometimes very transitory side effects of errant
code.  Frequently, the code causing the damage is quite distant
from the point of impact.  In many cases adding print statements to 
an ailing program has been known to change
the memory layout sufficiently to move or totally mask the problem.
I've  never (in 20 years) seen a 700 line loop or a problem that 
needed 300 passes through a loop to show up, although I'm sure
that both situations are possible.  

Being able to use Codeview may not be an advantage of MSC however
NOT being able to use Codeview is also NOT an advantage of Turbo C
over MSC.

In general, it is sometimes necessary to bang around in the
assembly level code generated by the compiler.  Codeview is
nice at those times.  Other debuggers (SYMDEB, DEBUG and adb)
are just about as useful but the Codeview user interface is
"nicer".
>
>     The idea of a hardware debugger, such as Periscope's, is valid;  if
>you need to see values of variables AFTER the system crashes, there
>ain't no other way.

There are other elements of the art of debugging beyond seeing the
contents of variables.  It's useful to know EXACTLY what your program
is doing as opposed to what you THINK it's doing.  Single stepping
(more precisely breakpointing) helps you to see EXACTLY what your
program is doing in large part because it forces you to examine
the structure and flow of your program.  Many of the "difficult"
bugs are those where you meant to write something other than what you
actually wrote.  There's a strong tendency to read past these
when you look at what you wrote, because you read what you MEANT
instead of what you WROTE.  Single stepping makes this kind of
bug show up rather quickly because it forces you to look at
something other that what you wrote.

>This [array bounds checking] is tremendously useful, and I don't see it in
>Turbo C or hear about it from Microsoft, although I have to believe that
>Borland will have this kind of feature in Turbo C long before MicroSoft
>hears about it. 

C doesn't do array bounds checking.  If Turbo C were to do array
bounds checking, it wouldn't be C.


-- 
Greg Laskin   
"When everybody's talking and nobody's listening, how can we decide?"
INTERNET:     greg@gryphon.CTS.COM
UUCP:         {hplabs!hp-sdd, sdcsvax, ihnp4}!crash!gryphon!greg
UUCP:         {philabs, scgvaxd}!cadovax!gryphon!greg

allbery@ncoast.UUCP (Brandon Allbery) (07/12/87)

As quoted from <3256@oberon.USC.EDU> by mlinar@poisson.usc.edu (Mitch Mlinar):
+---------------
| In article <719@imsvax.UUCP> paul@imsvax.UUCP (Paul Knight) writes:
| >     What I like about Turbo Pascal, and I don't seem to be seeing these
| >features in Turbo C, are the checks on system errors at run time.  A
| >number of things which used to drive me batty using state-of-the-art
| >Fortran compilers on mainframes never see the light of day in Turbo
| 
| I don't argue with the fact that Turbo Pascal has more error checking than
| either Turbo C or Fortran.  HOWEVER, this is more a fundamental difference
| between Pascal and C and NOT just a compiler nicety.
+---------------

May I also note that, since pointers and arrays are (almost) interchangeable
in C, checking array bounds will probably cause programs manipulating pointers
in a perfectly legal and correct way to blow up.

Example:  In Pascal, you can not new(ptr) to get an arbitrarily-sized array.
(I haven't tried it, but you may be able to new(fixed-size-array).)  In C,
this is easy:  ptr = (ptrtype) calloc(numelts, sizeof *ptr).  But, if you try
to bounds-check this, you either have to add huge amounts of code and tables
updated at runtime to show that "ptr" is an array of "numelts" elements AT
THE TIME OF THE CHECK (since next time it may be numelts + 1 elements), or
you decide it has to be a single element (thus making the program not work),
or you take the C route:  no checking at all.

The best way to check C programs is the "safe C" approach:  a C interpreter.
This, however, assumes that you have all the libraries to be linked in in
interpreter library form or in source.

Actually, it might be nice to have a "dcc" that compiles in code to load
and check tables of current allocations for variables and cause runtime
errors if you say "x = calloc(3, sizeof *x); printf("%lx\n", x[3]);".  (A
common error, since you said 3 and the highest element is therefore 2.)  This
is true of UN*X as well as DOS.
-- 
[Copyright 1987 Brandon S. Allbery, all rights reserved] \ ncoast 216 781 6201
[Redistributable only if redistribution is subsequently permitted.] \ 2400 bd.
Brandon S. Allbery, moderator of comp.sources.misc and comp.binaries.ibm.pc
{{ames,harvard,mit-eddie}!necntc,{well,ihnp4}!hoptoad,cbosgd}!ncoast!allbery
<<The opinions herein are those of my cat, therefore they must be correct!>>