PC-Lint Static Code Analyzer

    In order not to put the matter aside, I will continue the story about my experience with using static code analyzers. (Start here and here ).

    After trying Klocwork, I tried to interest the management in it, but the price of 30 thousand euros served as the main stopping criterion, everything else was no longer important.

    However, someone suddenly remembered that once the company had already acquired a license for some kind of code analyzer. This analyzer turned out to be PC-Lint. It turned out that no one was using it (after reading to the end, you will understand why), so they gave me the license, they say, play, if you're interested.

    Well, the system turned out to be the exact opposite of Klocwork. Starting from the command line, all settings via parameters or a configuration file, a list of files for analysis must be prepared manually. True, there was some kind of integration with Visual Studio, which, however, only allowed to avoid creating a list of files. Configuration files still needed to be written “by hand” in a text editor.

    The output is in a text file. When starting from Visual Studio - to the studio console, from where it could be clicked to go to the location of the alleged problem (already easier!).

    PC-Lint's biggest problem is the number of messages. On a relatively small project, with default settings, he issued more than 23 thousand comments! Having spent a couple of days viewing and turning off the 34 most frequent and, at the same time, not at all critical class of problems, I achieved a reduction in the total number of comments to five and a half thousand!

    And of course, in such a heap, several really important points can easily be lost, indicating a real buffer overflow or the use of an uninitialized variable.

    And for this very reason, those who bought it stopped using the tool. I stopped using it, having spent several days digging through thousands of warnings, finding, however, a couple of real critical problems and slightly improving the code style.

    You can “turn off” only all messages of a certain type, there is no possibility to mark one specific message as false positive.

    Of course, there is no tracking from build to build. You can focus only on the total number of messages.

    Problems found in the header files are duplicated every time this file is connected. If a file is connected ten times, then all ten times PC-Lint will display messages about all problems found inside. And given that he easily finds problems even in the files of the studio itself, especially in the implementation of STL containers ...

    At the same time, how the problem arises is also not shown in any way. Those. for example, he can report that it is possible to use an uninitialized variable in this place, but under what conditions it happens, he has to guess for himself (unlike Klocwork, which shows the full path from the beginning of the function to the problem point through all the branches).

    And to top it off, it only works locally. When working in a team, there is no way to easily and quickly report the problems found to the rest (only copy-paste of the text, alas), as there is no way to run it by all participants (unless, of course, a separate license is bought for each participant).

    Of course, PC-Lint also has advantages.

    The number of messages can be considered a plus under certain conditions. Despite the fact that most of the messages are related to style and almost never indicate a potential problem, it is worth recognizing that almost every message has a drop of common sense. And if (theoretically) fix everything that PC-Lint offers to fix, the code will clearly become better, more understandable and readable. But, as someone on the Internet said, “I want to program in C, not Lint!”

    An example of a “cosmetic” remark:

    It was:
    calib_offset = (int32)(full_offset / full_gain * 100000);
    

    PC-Lint here sees an ambiguity in reading: a / b * c - is it (a / b) * c or a / (b * c)?

    Accordingly, it became:
    calib_offset = (int32)( (full_offset / full_gain) * 100000);
    

    In my opinion, readability has increased!

    If the project starts from scratch and is not too large, then with a certain desire, you can also get the “Zero Problems” approach from PC-Lint. If, at the time of the first launch, the project is close to completion, then “Zero Problems” will be almost impossible to achieve.

    Among other advantages, I can distinguish the following:

    • a very good description for each warning issued (they are all framed in a separate large PDF document, it’s naturally impossible to automatically switch to a description from the studio);
    • a very large set of rules, for example, there are rules written on both books of Myers “Effective C ++”;
    • flexible configuration option - you can enable and disable each rule individually;
    • finds real problems well (it's hard to find them among the abundance of other messages);
    • price - much cheaper than other options ($ 389 for an unlimited time license).

    And finally - a couple of really found problem areas:

    It was:

        switch (SocketID)
        {
          case SOCKETID_1:
          case SOCKETID_2:
            break;
          case SOCKETID_3:
            doSomething();
            break;
          case SOCKETID_4:
            doSomethingElse();
          case SOCKETID_5:
            doSomethingElseSimilar();
          case SOCKETID_6:
            doAnotherThing();
            break;
          default:
            return ERR_SERVICE_NOT_SUPPORTED;
        }
    

    It became:

        switch (SocketID)
        {
          case SOCKETID_1:
          case SOCKETID_2:
            break;
          case SOCKETID_3:
            doSomething();
            break;
          case SOCKETID_4:
            doSomethingElse();
            break;
          case SOCKETID_5:
            doSomethingElseSimilar();
            break;
          case SOCKETID_6:
            doAnotherThing();
            break;
          default:
            return ERR_SERVICE_NOT_SUPPORTED;
        }
    

    If suddenly someone did not notice, the word break was missing there twice;

    void main_task(void *p_arg)
    {
      int status;
      // somewhere below…
      status = memory_init(&memory_config[0], memory_heap, sizeof(memory_heap));
      // and later “status” in never used…
    }
    

    The remark on this piece of code is rather stylistic - “The value of the status variable is not used anywhere”, but, in my opinion, not so meaningless - such code creates a false belief that the result of the memory_init function is taken into account somewhere, which, however, is not so.

    And it is much more “honest” to rewrite the code like this without declaring an unused variable and explicitly discarding the result.
    void main_task(void *p_arg)
    {
      // some code…
      memory_init(&memory_config[0], memory_heap, sizeof(memory_heap));
      // some other code
    }
    

    Of course, it would be more correct to check the result and perform the necessary actions in case of failure - but ... it’s good when the project is at an early stage, and changing the application architecture is still quite easy, and not when the project is already completed and in this place exception handling It wasn’t laid down architecturally initially (Is it possible to check the result, and then what? What can I do next if it signals a failure and the calling function does not have an exception handling mechanism?).

    And that’s why we need a static code analyzer that runs regularly (ideally after each build!), Along with the requirement “Zero warnings from the analyzer”.

    Of course, no analyzer can replace a competent developer, code review, and other development management techniques and methods. However, it can definitely make life easier for the whole team with proper use!

    Also popular now: