Fog Creek Software
Discussion Board

Do normal people use Lint?

Hi all,
We're writing cell phone games in C++. The API is really buggy, the emulator is buggy, and every phone has different bugs. And to keep things interesting, you use a different compiler for the emulator than you do for the phones.

So, we're attacking this beast head on, assuming that nothing works, ever, and throwing every defensive coding trick at it that we know. In the last month I've read a dozen books with titles like "More Super Safe Exceptional C++ Idioms and Common Pitfalls".. A big part of the motivation is that we have to pay a couple thousand dollars to get the application QC'd, and we have to keep paying that until the application passes.

Today I played with PC-Lint. I'm very happy, I've learned more weird quirks in C++ than I have in the last month of reading books about weird quirks. Maybe because I'm actually paying attention, since it's in our codebase.

However, almost all of the 2907 messages are nitpicky syntax things, not bugs. It wants me to put "static" in front of overloaded operator declarations. And cast 0 from int to long int when the function expects a long int. Cast function return values to void when they are thrown away. Put a little //lint comment when I don't want a no argument constructor for a class. A million little things like that.

I fear this will turn into some weird kind of unproductive insanity. I could spend a week eliminating all the messages, cluttering up the code with //lint comments and redundant casts everywhere, and may not get any real value from it. Or, I could turn off almost all of the warnings and potentially lose a lot of the value of using this in the first place.

So what's been people's experience with these types of tools? In the end, are they worth it? Or are these tools mostly popular with folks that tend to procrastinate and fiddle a lot?

Matt "Linty Coder" Sponer
Thursday, August 8, 2002

I swear by PC-Lint.

Troy King
Thursday, August 8, 2002

In the 3 years I used lint at Juno, 99.9% of the bugs that it found were this common mistake:

fprintf( s, "...%s...", CString());

when you needed to do

fprintf( s, "...%s...", (LPCSTR) CString());

so that the CString would get converted to the char* that fprintf wanted. [Interestingly this problem vanished in 32 bit MFC when they made a CString actually BE a char*, very clever bit of work].

The rest of lint was a waste of time. And the worst thing was that some of the developers thought it was a good idea to lint right before shipping, and they would make 2000 small changes to their code the day before they shipped, which was awful.

Joel Spolsky
Thursday, August 8, 2002

Joel, about the developers that were waiting until the last minute -- that's not an argument against lint, that's an argument against doing stupid things, especially at the last minute. To me, running lint is like a level 5 error checker... it's another way to check for something that might not be harmful, but should be checked anyway.

By your own admission, you were forgetting some casts. Wouldn't you hate to miss one that got cast incorrectly?

Troy King
Friday, August 9, 2002

Joel, you need to lint before the code gets checked in, not before the product gets shipped.

Friday, August 9, 2002

I used to run lint on platforms where the C compiler wasn't up to finding the problems, (GCC is quite good at warning about things itself) and run it as part of the build process: in the makefile you run lint & count the lines of output, too many means a build fail. Otherwise have it go on and throw the code through the compiler proper.

Katie Lucas
Friday, August 9, 2002

Other than the lint like warnings the compiler throws up you need to be sensitive to conversions.  Whenever the compiler warns about converting ints, floats and so on nail the cause and eliminate it.

Especially in an environment such as yours.

If there are warnings about uninitialised variables or variables defined but never used, eliminate those.  The uninitialised is an obvious nono but its easy to leave unreferenced variables and think they're unimportant but; if they're on the stack they take up space; if you have some buffer size issue then it may not be apparent in testing because your unused variable saves you (this is more commmon than you might think).

Simon Lucy
Friday, August 9, 2002

I use PC Lint and I like it. It's helped to find bugs and 'issues' that would have taken longer to find without it. It's a pain to use on an existing code base that hasn't had it run on it before, as there are so many issues to deal with, but once you use it regularly it's OK.

I'm undecided as to what is the best way to limit the number of messages it produces. At present I have a per library lint config file which contains the switches that are common across the whole library and then I have //lint comments in the source files themselves. You do tend to end up with quite a bit of 'lint noise' in the files though, but after a while you don't notice it...

I try to limit the scope of the //lint comments as much as possible, this means I tend to have some in blocks in the header file, some in blocks in the source file and some that just turn the warning off for the next line... With all of the lint comments I try to include the message that it's turning off in the comment, so I'll end up with something like:

//lint -e{1933} call to unqualified virtual function

Any messages that can be turned off with -esym are placed at the top of the file and this reduces the 'lint noise' in the source itself...

Len Holgate
Friday, August 9, 2002

I develop systems in Java, and I swear by (and often at) a package called "checkstyle".

Part of our ant build process is to run checkstyle on all the code.  This ensures consistent style, and helps us avoid lots of pitfalls.

I know it's off topic, but I provide the comment in case any Java hackers happen by.

Patrick Carroll
Friday, August 9, 2002

Once, someone ran some overpriced Rational tool to critique a package I wrote.  The one useful thing it found (out of like a hundred) was that I called someone else's lib which compared floats directly, without using intervals.  So I suppose it's a nice lazy way to detect errers in the code of someone you don't trust.

Compiler writers know not to make annoying little warnings, or people would simply ignore them.  So I suppose these tools are made to fill in that gap.  These warnings are not to be absolutely followed, but to be taken for what they are -- a computer whining to the best of its machine ability.

Saturday, August 10, 2002

I did not know lint before my current project where they use lint intensively. First I thought this is really a nice tool helping to get bugs fixed at compile time. I really love a coding style that I call "compiler supported coding", concentrate on the main thing and then fixing things up with compiler aid, like if (... = ...), missing declarations, etc. I found out that this is really much faster then trying to do code mostly perfect in the first way. Okay, but back to lint. I used lint then and instead of getting any real bug fixed I got only annoying messages. And whats more I usually use compilers where I get all the important error messages so for what I need lint ? If I want these messages I compile with Intel Compiler and reed the remarks ... of course I don't read the remarks. I think today's compilers make lint superfluous. They only add work and take the focus away from the real tasks to perform. If you really want to use lint, then make a run per month and look if anything useful is inside.

And back to my current project I work in as part of the so called "stability task force", the design is a catastrophy. The code is not working, the code is about 10 times to complex, the project is delayed 3 years and wasted 100 millions Euro (I am from Germany), the code is slow and does not meet the requirements but the code is perfectly lint clean ! Any questions ?

Wednesday, August 28, 2002

There was a study done at a very large cell phone company I used to work for that compared the number of lint
warnings vs the number of bugs found in the field. There was a very strong, positive correlation between the lint warnings. When the number of lint warnings dropped, the number of bugs found in the field dropped. The shape of the two curves ran parallel.

My experience is that given an appropriate filter, most of the lint "warnings", most of the time, are indicating coding errors. Yes, there are insignificant and/or trivial warnings, but what a simple and cheap way to find bugs!

Here's some process heuristics:
- Make lint part of your nightly build. (if you don't have a nightly build, read a book).
- Make a rule "No lint warnings" in the nightly build.
- Have a weekly or bi-weekly build where the "No lint warnings" is strongly enforced
- Have 4 levels of warning filters: VerySlack, Slack, Normal, Strict
- the first time you use lint, start with VerySlack.
- When you've reached 0 warnings, start using Slack.
- When you've reached 0 warnings, start using Normal
- periodically run Strict to see what the report says. If there's are any significant warnings, consider not filtering them in Normal.
- The Gimpel PC-Lint manual goes one further and has some settings for turn-the-tap-way-up. I'd try that every once in a while.

By the time you are ready for a candidate release, there should be zero warnings and therefore no last minute changes.

Use lint. be happy. sleep well.

Tuesday, June 15, 2004

Sammy says:
"Compiler writers know not to make annoying little warnings, or people would simply ignore them."

Compiler writers are trying their best to detect lousy code, and provide some feedback, otherwise crappy programmers blame the compiler for their mistakes. Otherwise, the compiler writers wouldn't generate warnings at all. They have other, more substantial, worries like whether or not they are generating correct object code, whether or not they are conforming to the language standard, whether or not the optimizer works correctly, etc.

The "annoying little warnings" are generally not warnings but in fact errors. Usually they can be ignored because the developer has coded to a convention not detectable by a static analysis tool like lint or a compiler. e.g. I use a long when I "know" that the value it will hold will never be more than 255, so I "know" it's ok to assign to a char.

Coding by convention is a very fragile way to code. Maintainers will eventually break the conventions causing very difficult to track down bugs, spurious bugs, coupled bugs, etc. When a development team does this, the initial development flies by but then the code slowly deteriorates over time into something that can't be enhanced any more.


Tuesday, June 15, 2004

Andreas says:
"I really love a coding style that I call "compiler supported coding", concentrate on the main thing and then fixing things up with compiler aid, like if (... = ...), missing declarations, etc. I found out that this is really much faster then trying to do code mostly perfect in the first way."

Is your project in any way related to public safety?

Tuesday, June 15, 2004

*  Recent Topics

*  Fog Creek Home