Dear Mr. Plauger:
There are a number of aspects of the current state of the art of software engineering that I find less than satisfactory. They are
1) Bug-infested tools
2) The dearth of productive engineering tools
3) The programming languages themselves.
First of all, I have used Lattice C, Turbo C, and Microsoft and Borland C/C++ compilers. Our group chose the latter two for their third-party and Windows support. First I used Lattice C 3.1. It didn't do floats but doubles seemed to work OK. Next I used Microsoft v5.0. It optimized code out of existence. Because of that we switched to Turbo C/C++. It refused to do assignments of floating point (float or double) literals in the range between 0 and 1!
This problem only occurred when linking together 20-odd modules, In a three-module test program all worked fine. Due to project deadline pressure I was never able to whack away at the 20-odd modules to the point where the problem went away in order to determine its cause. I worked around it. This problem was also present in Borland C/C++ 3.0, but does not occur in version 3.1 with identical source code. I have seen two instances where Borland C/C++ 3.1 handled the following snippet where the function returns the value 1 by not taking the if:
if ( func() ) // returns 1 do_something(); // never executedChanging this to the following worked, however:
status = func(); if ( status ) do_something()My first gripe about the state of the art is that compiler vendors seem to concentrate on features like IDEs, 32-bit versions (64-bit next, no doubt), Windows support, etc., while basic functionality is not solid. Floating point seems especially difficult for these people. (You'd think that after ten years of writing C compilers...) I really don't know if Borland C/C++ v3.1 has floating point problems; I just haven't seen any problems so far. Now if Borland and Microsoft are the least-buggy products on the market, I'd hate to see the others. I would love to be able to trust the compiler, but that seems to be wishful thinking. At least we have debuggers to go roto-rooting in the generated assembly code.
More and more vendors are charging for phone support. Now I get to pay them for reporting bugs in their products. Borland actually told me to call their 900 number to discuss a bug! No thanks! Along with the bug situation, I wish compiler error and warning messages were more accurate. In many cases I have to ask myself, "Now what does it really mean?" I use PC-LINT religiously. To the compiler vendor's credit, error and warning messages have been getting better in recent years.
Now lets add C++ on top of this whole mess. I enjoyed your article, "Programming Language Guessing Games" in Dr. Dobb's (October 1993). I agree of course with your suggestion to "pick a subset of the [C++] language that minimizes surprises, learn it well, and don't stray from it." The problem is that the compiler vendor chooses to support everything that looks like it will make it through the ANSI committee. If they can't get some of these simple things solid (like the function return value example above) how can I trust them to do some of the complicated things you have described for C++? Even if I do restrict myself to a subset of the language, it could be that the other features induce bugs in the parts that I am using. The bottom line is that the majority of our time is spent on maintenance. Compiler bugs cost us. Secondly, the support tools available do not help me with software engineering (as opposed to hacking which I define as, "code it first without thought of design, document it later") as I would like. Diagrams are a neat idea, but then we have to translate the diagram into code by hand and translation is where errors creep in. Management might go for the time spent on diagramming if automatic code generators were available. Code generators for Windows screens and other user interfaces are generally available, but I haven't seen any for other parts of a program. A framework generator would be nice. Hardware engineers have schematic capture and printed-circuit-board layout tools including auto routers, but as software engineers, we do analogous things by hand. Also, I've yet to see a decent cross-reference generator after evaluating several. The ones with usable output are way too slow. I use GNU CTAGS, but wish it did more. I know of no general purpose, highly configurable cross-reference generator. We have written our own programs and editor macros to insert comment blocks for functions and modules and for extracting those into a Word document, but so much more could be done. I am beginning to write add-on tools for Codewright, a very extensible Windows programmer's editor. Thirdly, despite some ugly features of C, I like it a lot (more than Pascal, Modula-3, Eiffel, etc.). For example, C overloads the static and void keywords, allows functions to return pointers to automatic variables, and various other gotchas mentioned in Andrew Koenig's C Traps and Pitfalls. (Being able to execute an array of opcodes is a feature?) But for the sadist, C++ is a real treat. Now we have not two but three meanings of static and not two but four meanings of void!
C and C++ violate many of the accepted guidelines of language design. Many things can be done several different ways, much of it behind the scenes. I shudder whenever I read one of your articles concerning C++, your latest in The C User's Journal on the Standard C++ library included (P.J. Plauger, "Standard C: Developing the Standard C++ Library," CUJ, October 1993). I know that I cannot avoid learning C++, but hopefully it will be replaced soon with something simpler. We need new paradigms and metaphors to handle advanced concepts. Languages will have to become more complicated, but they should be as simple as possible. I like the approach taken by Meyer in Eiffel of including an extensive set of libraries. The less I have to write myself, the more productive I am. Hopefully, libraries supplied with compilers are well thought-out and bug-free. I wish Borland C/C++ came with the library support that Eiffel or NextStep Objective-C does. A collection of third-party classes or libraries does not have the consistency that a single-sourced library does. I have only touched the surface of some current problems in the software industry. What I would like to know is:
1) Which in your experience are the least-buggy C/C++ compilers?
2) Do you know of a diagrammer w/code generator? What other engineering tools have you found to be helpful?
3) Do you know of any cross-reference generator that outputs a list of identifiers including the module name, line number, and function (if any) they were found in, and that is fast?
4) What do you think of Modula-3, Eiffel, and IBM's Object REXX? Thank you in advance for your help. Thanks for your excellent articles. Please keep them coming.
[email protected]
Bruce Dickey
Micron Semiconductor, Inc.
2805 E. Columbia Rd., MS 892
Boise, ID 83706
Whew! You raise a whole slew of issues. I agree with you almost across the board, except that I am a bit more sympathetic to the plight of all those compiler vendors out there scrabbling for market share in a turbulent industry. I guess that comes from selling compilers myself for ten years. Growing complexity seems always to offset gains in our ability to manage software development and reduce shipped bugs.
I don't know how to answer any of your questions at all well, but I invite other readers to chip in. My opinion of Modula-3 and Eiffel, for what it's worth, is fairly simple. Both offer interesting combinations of features, but neither has quite pulled off the synergy of C or C++. I don't know enough about REXX to comment. pjp
Dear Editor,
My compiler issues an error diagnostic on the call to g in the code fragment shown in Listing 1, but no error on the call to f The error claims that there is a pointer mismatch in the argument. I am using Digital's DEC C compiler under OpenVMS on their new Alpha processor. When I contacted DEC's customer service, they explained that the ANSI standard allows conversion from a pointer to a qualified type to a pointer to a non-qualified type, but does not allow 'ignoring' the qualifier for a pointer to a pointer to a type. Their argument seemed somewhat niggling to me, so I wanted to appeal to a higher authority. How do you think a compiler should handle this code (shown in Listing 1) ? Sincerely,
Dick Hile
T and B Computing, Inc.
24 Frank Lloyd Wright Dr.
P.O. Box 302 - Lobby A
Ann Arbor, Michigan 48106-0302
DEC is correct. The distinction may appear niggling to you, but we meant to do it that way when we wrote the C Standard. pjp
Dear Mr. Plauger,
I would like to add my two cents' worth to Mr. Mike Musielski's comments (CUJ, October 1993) on the nature of C as a language. ("Is C a language?" was his opening question.) The short answer to that question is, no, C is not a language. Neither is any programming language. The programming-as-writing analogy is interesting, but like most analogies it is partly true and partly dangerous.
A programming language is really a notation system: defined narrowly, conceived as a formal means of expression, and limited in its range of expressiveness, at least when compared with natural languages. No programming language is used as an end in itself (except of course by participants in Obfuscated C contests), whereas a natural language is used that way all the time by artists whose only goal it is to explore the language's poetic possibilities. This is the main reason why programs, no matter how short, cannot be compared to short stories or other forms of fiction.
Nevertheless, there is a basis for the analogy. Like natural languages, programming languages do evolve and adapt themselves to new situations and conditions. And as they do, new vocabulary creeps in, functions begin to overlap, and things begin to get well, messy. Even standards cannot clear up all ambiguities: there will always be more than one way to skin a cat. You can say "pass away" or "kick the bucket," just as you can use strtol or atol. Both elements in each pair approximate, but do not exactly map, the same idea. How are you to recognize when it is appropriate to use one and not the other? This is what Mr. Musielski wants to know.
There are some useful texts out there. I suggest Mr. Musielski look at (again, if not for the first time) The C Programming Language, by Kernighan and Ritchie. Another book I have found useful on occasion is C Lab Notes, by Flanders and Holmes. This book has a nice feature in that each chapter has at its head a list of the tasks that are to be explored inside ("forward and reverse scrolling," "sending a message to another node," etc.). And, not least, The C Users Journal is itself very instructive in matters of language use. None of these texts is consciously "literary," but all take the implicit stance that a programming language is an idiom to be mastered. Mastering the language (your "material") is the goal of literary writing as well.
I think what might be very beneficial to Mr. Musielski (and others, myself included) would be a kind of reverse dictionary: a list of common tasks along with the range of functions, procedures, tools, etc. that could be used to fulfill each task's requirement. Such a book could not possibly be exhaustive and the organizational problems would be daunting, but a good text like this might be useful enough to be a starting point. Of course, as writers learn from writing, programmers learn best from programming. There is still no effective substitute for trial and errormany trials, many errors.
Sincerely,
Michael Nichols
1725 York Avenue
New York, New York 10128
Thanks for your insightful comments. pjp
Editor:
I found Robert Watson's "DMA Controller Programming, in C" (CUJ, November 1993) interesting, particularly of course the protected-mode details, but found his conclusion, "the technique is actually very easy to use" laughable, considering what he had just painstakingly documented. "Virtually impossible" is more like it. I agree with his further conclusion: that DMA is increasingly obsolete, since fast CPUs deal with dedicated card memory blocks more expeditiously (and of course the implication that such memory is relatively cheap in modern times DMA was originally a cost as well as speed feature).
I also think along the way he erroneously minimized the difficulties involved in getting hold of a DMA buffer in real mode ("in real mode, generating a DMA buffer is relatively easy"). I hope I'm missing something, but in my source where I tried to accomplish this there are three or four failed attempts commented-out, and I'm not at all happy with my current effort, shown in Listing 2.
If anybody knows how to do this rationally, stop me before I code again! The crude strategy here is to keep getting buffers, and if they're no good won't do DMA because they cross a physical boundary retain the offending part of the buffer and keep trying; and then when we get a good one, free all the chunks accumulated along the way. This approach relies on totally unreliable assumptions about memory allocation, and really comes down to a "keep trying until you give up" approach.
Operating systems in 80x86 land get to own low memory, where it is relatively easy to set-up a good DMA buffer. Programs, on the other hand, can be loaded at any address, and can't make any such arrangements except, as far as I can figure out, by using awflike the example.
And incidentally, who owns the VDS (Virtual DMA Services) interface mentioned in the article? I have a vague idea how one goes about getting in touch with DPMI; is VDS one of these things that comes with DOS extenders and/or Windows or what?
j.g. owen
Software engineer
31 Darby Drive
South Huntington, NY 11746
cis 71121,625
To the Editor:
Concerning the letter from Lawrence H. Hardy in the 11.12 issue of CUJ, page 136, asking for information about PCX graphics:
And I thought my memory was going... Actually, this might instead be seen as an illustration of the need for a CUJ index depending on one's perspective of course. At any rate, whilst fumbling through a stack of old Journals seeking edification on a particular coding problem, I came across Vol. 9, No. 8 (August, 1991). Emblazoned across the cover was "PCX GRAPHICS DOCUMENTED!" And sure enough, there on page 89 was a decent discussion of the topic by one Ian Ashdown, complete with bibliography.
I would also like to join Ian Somerton (p. 127) in expressing concern, if not alarm, at the exponential increase in C++ coverage of late. Perhaps someone on your staff misread it as C**?
Sincerely,
Scott Swanson
Box 75
Pendroy MT 59467
I am notorious within R&D for my instant amnesia, once an issue goes out the door. You're right that an index to CUJ is indispensable, and the folks back in Kansas have anticipated your wish. As for C++ coverage, that happens to be an area of intense interest in our community at the moment. We haven't forgotten about C by any means, but the mix what we publish is strongly influenced by the mix of what's proposed to us in the way of articles. pjp