What is "Static Code Analysis"?

Go To Last Post
72 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The MISRA folks talk about the importance of Static Code Analysis. What is it, and what tools are available for it? Anything built into gcc? What does it NOT do?

 

<edit> Tried to do some searching on the internet with little concrete information </edit>

 

Thanks

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Thu. Nov 17, 2016 - 11:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Imagecraft has MISRA rules built in, if that helps.  

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So far, I've only used gcc with an IAR project at the University a few years ago.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"static" means it's done by looking at the (source) code without running it; eg, checking it against MISRA rules, your coding standard, etc.

 

Lint is the classic example.

 

https://en.wikipedia.org/wiki/Lint_(software)

 

https://en.wikipedia.org/wiki/St...

 

Of course, the compiler does some of this - and gives you Errors for illegal code, and Warnings for legal but "doubtful" bits.

 

GCC can give an extremely wide range of Warnings ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
What is it, ...
Performs additional evaluation of semantics and pattern matching that a compiler does not.

A compiler's purpose is to move through source code as fast as possible and correctly do that but at minimal essential for completeness.

A common set of defect patterns that's a part of a static analyzer is the Common Vulnerabilities and Exposures (CVE).

ka7ehk wrote:
... and what tools are available for it?

  • Light (lint)

IIRC, part-and-parcel with the creation of the first C compilers.

A common part or parts in the software development packages for Un*x, Linux, BSD.

A feature in common IDE (Microsoft Visual Studio, Apple Xcode)

 

  • Medium (inter-module, whole program)

PC-lint

 

  • Heavy (deep, possibly finds subtle defects)

Polyspace

Coverity

etc (an increasing quantity)

 

ka7ehk wrote:
Anything built into gcc?
Not that I'm aware of.

LLVM clang has some static analysis that, IIRC, is a part of Xcode.

 

ka7ehk wrote:
What does it NOT do?
Some are difficult to correctly configure.

Can be too much; assertions and a lint are sometimes adequate.

 


CVE

CVE - Common Vulnerabilities and Exposures (CVE)

https://cve.mitre.org/

The Standard for Information Security Vulnerability Names

Gimpel Software

Gimpel Software

PC-lint and FlexeLint

The Leader in Static Analysis for C/C++

http://www.gimpel.com/html/index.htm

http://clang-analyzer.llvm.org/ 

Gamasutra: The Art & Business of Making Games

Gamasutra

The Art & Business of Making Games

In-Depth: Static Code Analysis

by John Carmack (id Software co-founder and technical director)

December 27, 2011

http://www.gamasutra.com/view/news/128836/InDepth_Static_Code_Analysis.php

...

Dave Revell: @dave_revell The more I push code through static analysis, the more I'm amazed that computers boot at all.

laugh

via http://www.ganssle.com/tem/tem282.html#toolsandtips

http://www.ganssle.com/search/search.html?zoom_query=static+analysis&zoom_per_page=100&zoom_and=1&zoom_sort=0

The Ganssle Group logo

Automatically Debugging Firmware

by Jack Ganssle

Major rewrite: May, 2014

http://www.ganssle.com/dbc.htm

...

 

Assertions as Contracts

...

 

Side Effects

...

Couple the above definition (extended C assert) with the use of PC-Lint (you do use Lint, don't you?

...

Edit : clang analysis URL

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Thu. Nov 17, 2016 - 11:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the responses, above. They filled in a bunch of empty holes.

 

Jim

 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I read the thread title and the first thought that entered my head was "bane of my life"!! :-/

 

Anyway you know how when you build code with the compiler it tells you things like "warning assigning int to pointer without cast" and such warnings get even more voluminous if you use "-Wall"? Well static code analysers just take this to the next level. As Andy says Gimpel's "lint" is often considered the classic but that's maybe only because it was probably the first in widespread use.

We used to have Makefiles that would run our source through lint first before passing it to the compiler. If lint gave any warnings/errors it never even made it as far as the compiler.

 

The kind of things it would spot that a compiler won't are things like:

int main(void) {
    int data[10];
    int n;
    
    for(n=0; n < 15; n++) {
        data[n] = n;
    }
}

If I build that:

$ gcc lint.c
$ 

no warnings. If I build that with -Wall I get some warnings:

$ gcc lint.c -Wall
lint.c: In function ‘main’:
lint.c:2:9: warning: variable ‘data’ set but not used [-Wunused-but-set-variable]
lint.c:8:1: warning: control reaches end of non-void function [-Wreturn-type]

They are useful but what I really want someone to tell is that I am writing to 15 positions of an array that only has 10 entries!

 

Lint and other static code analysers would spot things like this.

 

Over time we have used various other static code analysis tools (including cppcheck - which is both C and C++ despite the name) but these days we use the terror that is Klockwork:

 

http://www.klocwork.com/programs...

 

We use it principally for MISRA checking (please, please someone, let us use malloc()!!!) but also for code defects in general. It spots lots (I mean lots!) of stuff besides the MISRA compliance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have used Klockwork and it's BIG, but the warnings are real, (but often not relevant for how the code is used today) 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Remember that MISRA is a guideline, you are free to ignore it (at your own peril), overall its use has improved my coding!  

 

 

Jim

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not when you are trying to sell your product to Audi, VW, Mercedes, Daimler, Jaguar-Land Rover and all the rest - they are pretty insistent about this stuff! The MI in MISRA is "Motor Industry"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't believe the OP mentioned anything about MI in his post.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One of the things I really hate to see is this:

 

if ( 1== counter ) ...... 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sparrow2 wrote:
One of the things I really hate to see is this:
And yet that is the "safer" way to write that of course.

if (counter = 1) ...

still compiles even though the programmer meant "==" not "=". Yet:

if (1 = counter) ...

causes an error when the programmer made the =/== mistake. That's why folks do it.

 

But I agree, the first time I came across this was when we first bought in a TCP/IP/HTTP library back in the late 90's and all the if()s were "the wrong way round". There is something naturally unsettling about "1 == counter" !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did some speed tests of compares with switched operands using CVAVR, it was slightly faster under certain conditions. Not sure it still is, compiler evolves.

It all starts with a mental vision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

While not exhaustive I tried this in GCC:

#include <avr/io.h>

int main(void)
{
    if (37 == PINC) {
        PORTB =0x55;
    }
}

got this:

main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	in r24,51-32
	cpi r24,lo8(37)
	brne .L3
	ldi r24,lo8(85)
	out 56-32,r24
.L3:
	ret

I then switch the if order and compared:

$ diff avr.s avr.s.1
$

So here it is 100% identical whichever way round you put it.

 

But it's not really about speed, it's about the safety of the code you write.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The application where this might apply is a "public infrastructure" one. Certainly, not MI, but one that MIGHT need insurance protection which, in turn, MIGHT insist on MISRA. So, I am simply trying to think ahead, here.

 

Really do appreciate the comments and insights!

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An add-on to IAR EWAVR :

IAR C-STAT Static analysis

https://www.iar.com/iar-embedded-workbench/add-ons-and-integrations/c-stat-static-analysis/

...

It helps you improve your code quality as well as prove alignment with standards such as MISRA C:2012.

...

Includes approximately 250 checks mapping to hundreds of issues covered by CWE and CERT C/C++

...

What is CWE and CERT C/C++?

CWE, the Common Weakness Enumeration, is a community-developed dictionary of software weakness types.

CWE provides a unified, measurable set of software weaknesses in order to better understand and manage them and to enable efficient software security tools and services that can find them. Read more at cwe.mitre.org

The CERT C/C++ Secure Coding Standards are standards published by the Computer Emergency Response Team (CERT) providing rules and recommendations for secure coding in the C/C++ programming languages.

More information is available at www.cert.org

...

Can I run C-STAT from the command line?

Yes.

...

If static analysis is too onerous for one's development process (slow, hinders creativity, it's a fire hose) then invoking it within continuous integration (CI) can ease the use (CI runs in the background leaving foreground for the IDE)

First cut is by your creativity and that should flow; other cuts (analysis, review) proceed at a slower pace.

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gchapman wrote:
then invoking it within continuous integration (CI) can ease the use
+100

 

We haven't enabled it yet but the Jenkins that gates our pushes in Gerrit will eventually be predicated on passing Klockwork so it simply won't be possible to push code that is not Klockwork (MISRA) compliant.

 

But to work this sort of relies on all your engineers to kind of know all of MISRA C and MISRA C++ (and whatever other rules you are mandating) as they code. Otherwise they will be increasingly frustrated that they can never push anything into the repository!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
So here it is 100% identical whichever way round you put it.
 
But it's not really about speed, it's about the safety of the code you write.

I totally agree. I think my test compared to variables, not a variable and constant. I determined speed via io pin. It likely had to do, other tasks using variables, and how that worked out.

It all starts with a mental vision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KitCarlson wrote:
not a variable and constant.
But that's not the point here. It doesn't really matter if you use:

if (a === b)

or

if (b == a)

because if you make the =/== error then you are going to make an assignment come what may. The important thing is with constants:

if (7 == a)
if (a == 7)

if the classic =/== error is made then those become:

if (7 = a)
if (a = 7)

one compiles and one causes a desirable compiler error. It's just that since childhood we've all been brought up to ask "is a equal to 7" not "is 7 equal to a". It sounds positively revere polish!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
What does it NOT do?

 

It won't detect flaws in your design.

 

It won't verify that the code actually does what you meant.

 

It won't detect flaws like:

 

if( 1 == value )
{
    // The value is 10, so do this stuff ...
}

etc, etc, ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the additional comments. 

 

Just thinking, for a moment, (Bad Thing, sometimes !), I wonder why there can't be something that can be invoked via make that would provide more extensive code testing than the minimum required for a successful compile?

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Nov 19, 2016 - 05:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

I wonder why there can't be something that can be invoked via make that would provide more extensive code testing than the minimum required for a successful compile?

 

clawson wrote:

We used to have Makefiles that would run our source through lint first before passing it to the compiler. If lint gave any warnings/errors it never even made it as far as the compiler.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I missed that detail. Thanks.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
... I wonder why there can't be something that can be invoked via make that would provide more extensive code testing than the minimum required for a successful compile?
In the context of Microsoft Visual Studio, lint (/analyze) can be invoked from the command line and likely also via MSBuild.

IIRC Atmel Studio invokes MSBuild.

I'm not certain that Atmel Studio is compatible with Visual Studio; been stated that such is easier with Hyper-V (Visual Studio in guest, Atmel Studio in host).


Microsoft

Developer Network

Code Analysis for C-C++ Overview

Visual Studio 2015

https://msdn.microsoft.com/en-us/library/d3bbz7tz.aspx

...

Command-line support

...

Microsoft

Developer Network

MSBuild1

Visual Studio 2015

https://msdn.microsoft.com/en-us/library/dd393574.aspx

...

Using MSBuild at a Command Prompt

...

Microsoft

Developer Network

/analyze (Code Analysis)

Visual Studio 2015

https://msdn.microsoft.com/en-us/library/ms173498.aspx

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll point out that compilers check for a lot more errors than they used to.  Our "static analysis" step at my last employer involved about 6 different checkers, starting with "thou shalt compile with -Wall", progressively working its way up through more thorough, slow, and expensive tools (ending with klocwork, IIRC.)

Things are much easier if you start your program with this sort of process, rather than trying to add SA to a large existing source base. :-(  (klocwork in particular would produce a lot of "false positives" in our codebase.  That had to be approved and added to exception lists. :-( )

https://en.wikipedia.org/wiki/Li...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

... I wonder why there can't be something that can be invoked via make that would provide more extensive code testing than the minimum required for a successful compile?

In the context of Atmel Studio, there's a Cppcheck extension but it's for Atmel Studio 6.

For Atmel Studio 7 could add the current Cppcheck on Windows as an external tool and via a pre-build event.


Cppcheck - A tool for static C/C++ code analysis

http://cppcheck.sourceforge.net/

http://cppcheck.sourceforge.net/manual.html#idp26094784

Visual Studio

You can run Cppcheck on individual project files (*.vcxproj) or on a whole solution (*.sln)

...

https://gallery.atmel.com/Products/Details/27c5be13-b1d6-4c01-9bf2-711ec4790b94 (CppCheck Integrator (Beta) - Atmel Gallery)

http://www.atmel.com/webdoc/GUID-ECD8A826-B1DA-44FC-BE0B-5A53418A47BD/index.html?GUID-FCEEDC41-5F8D-4D79-AC89-99A6D7422A0B (External Tools)

http://www.atmel.com/webdoc/GUID-ECD8A826-B1DA-44FC-BE0B-5A53418A47BD/index.html?GUID-D42F376A-5538-4C9A-A8A3-606B3573D8C8 (Build events)

 

Edit : typos

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Sun. Nov 20, 2016 - 02:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps, this topic isn’t that acute, but these are my 2 cents. Besides the above mentioned static analyzers, there is a good selection of other useful tools (http://www.softwaretestinghelp.com/tools/top-40-static-code-analysis-tools/).

Speaking about the MISRA rules, some analyzers check the compliance of the code with these standards (Coverity, Klocwork, Parasoft and others), and some - like PVS-Studio don’t. As the developers state in their blog "Such diagnostics bulk up the analyzer output and instead of searching for real errors, a person starts fighting with thousands theoretically good, but having no influence suggestions of the code improvement".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Is it me or does that post look a LOT like spam??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It also won't tell you if you have a bad oscilloscope.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does look a little suspicious, but it's an interesting point in the blog.

 

Would be good to see how well it detects the types of errors that, say, MISRA is designed to prevent ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Part of their argument is downright stupid, IMO. More or less "coding standards does not avoid 'real errors'". I can't think of one interpretation of "real errors" in this context that does not make that argument stupid, ignorant or downright wrong.

 

They could have been content with saying "our analyzer finds errors that slip through e.g. MISRA, so use both."

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The MISRA C 2004 document can be found here: https://tinyurl.com/misrac

 

I worked at a large agriculture vehicle company and they had their own programming guidelines similar to MISRA. They had their own program development process and all sorts of guidelines and standards. Every line of code went through Lint and Polyspace and was checked for code coverage and then went through a code review with at least 3 engineers, then the code was sent to a company that could somehow check if there was any public domain code in there. You were lucky if you could produce 5 lines of code an hour.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey SG22! Don't take this personal or "ad hominem" but I'm going to mark/report that as inappropriate and subject to possible removal. The MISRA documents (both C and C++) are copyright and licensed for a fee.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it is only the 2004 version

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's rarely a good idea to use numbers in your code.  Except in enums.

int main(void) {
    int data[10];
    int n;
    
    for(n=0; n < 15; n++) {
        data[n] = n;
    }
}

 

int main(void) {
    enum   {
        Max_data = 10,
        };
    

    int data[Max_data];
    int n;
    
    for(n=0; n < Max_data; n++) {
        data[n] = n;
    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What does  the enum do in this case that a number won't? Does it effectively create a constant? Why not use a define?

#define MAX_DATA 10

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C++ programmers hate defines.  laugh​   Enums exist only in the class where they are defined.  But yes, a define also gives a name to a number.  I guess that was your question.

I think you understand why you would use a name rather than a number. 

 

I suppose you noticed I used Max_data twice.  In the original code, for illustrative purposes, 10 was used in one place and 15 was used in the other.  Also sometimes the array size is used in more places.  Using names instead of numbers is also convenient if you later decide to change the size of the array, because you only have to change the size in one place.

 

Sometimes a number can appear in the middle of a statement and cause you to wonder "what is that?", and "where the heck did that come from?".  Using a descriptive name won't cause you to scratch your head.   

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Agree on names. Was puzzled about why you chose Enum. Can't you have #defines that only have the scope of the current function (or module or class)?

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
Can't you have #defines that only have the scope of the current function (or module or class)?

No: because #defines are a preprocessor thing - therefore, they are gone before the compiler proper ever sees them!

 

All the compiler ever sees is the magic numbers.

 

Another advantage of enums, because the compiler can see them, is that it can generate debug info for them.

 

Thus the debugger can display the enum names - instead of just the magic numbers.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good to know (and understand)!

 

Am a bit confused, though. If I put the following a the start of, lets say, i2c.c

#define MAX_BYTES 5

Is this "visible" in other code modules? Say, uart.c?

 

Also, I think that I read, right here, not terribly long ago, that if I write

 

void foo(void) {
    
    #define MAX_BYTES 10
    uint8_t j;
    
    for (j = 0; j < MAX_BYTES; j++) {
        //do something here
    }
}  //end of foo()

then, MAX_BYTES is not visible outside of foo(). So, is MAX_BYTES visible by other functions in the module that contains foo() ? Or, not visible?

 

I understand the benefit of having visible names and debug information for "constants". My question is about the two cases, above, which is what I was thinking about when I wrote message #39.

 

Thanks

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

 Can't you have #defines that only have the scope of the current function (or module or class)?

 

Jim

awneil has some good points.

 

I haven't used C in many years, so take everything I say about it with a grain of salt.  But to answer your question, I guess if you put a #define in a .C (or .CPP) file it would only apply to that file.  I would put it after any #includes though because if you put it first, I think it would apply to the included files.

 

C++ programmers think about classes and C programmers think about files.  I only have room in my brain for one language.  wink

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

it is only the 2004 version

 


Just because it's not the latest version this does not make the copyright go away.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C has the concept of a 'compilation unit. When you compile i2c.c the compiler only 'sees' i2c.c and the include files. When you compile uart.c, the compiler only 'sees' uart.c and the files it includes. The compiler outputs an object file. Then it is the linker's job to knit the separate objects together into one. Thus the h file is the 'go between' for the file that wants to use something in another file.
In addition to what steve mentions, there's also the issue of 'type safety' - using variables in a correct manner. #define has no type safety - it just does a text substitution.
In c++ you can do something like this:
const uint32_t piAsInt 31412;
The idea is that the compiler will interpret this as a constant and not allocate any ram for it.
The intention is to give the compiler hints as to what you want and give it the work of checking that you did what you intended. The net result is to have code that works exactly as intended. Less bugs in.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Type checking is an important safety point about constants. Had not considered that.

 

And not, in any way, arguing against enum. Just trying to understand what applies, where.

 

Question: what is the "proper" way of making an enum visible in several files? Can you assign a type to an enum?

 

Thanks

Jim 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To make an enum type visible in several compilation units I would typedef it in a header file.

To make an enum variable visible in several compilation units is just like any other variable - do an extern declaration.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, Johan -

 

Appreciate that. So, does an enum occupy memory space like a variable? If its not a compile-time text substitution, is there any other option than ram? Well, maybe flash, but that does not seem like a benefit.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Thu. Jun 8, 2017 - 04:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're confused now.

If you've defined a variable of an enum type it occupies memory (with the usual comments about optimization, of course). Just like any other variable. There is nothing special to enums in this sense.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
// file scope:

enum menage { INE=1, TOO=2, TRASE=3 } ;  // no memory
typedef enum menage menage_t;  // no memory

menage_t fredgailhank=INE;    // probably memory
static const menage_t hankivanjake=TRACE;  // with opt, probably no memory

int players[hankivanjake];  // valid C++

 

IIRC even before the new-fangled class enums, C and C++ did enums differently.
In C, one could implicitly convert between enums and ints in both directions.
In C++, only from enum to int.
In C, IIRC the types of the enum constants are int (!!)
and sizeof(enum menage) == sizeof(int) .

Not sure about C++.

 

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
does an enum occupy memory space like a variable?

As Johan said, an enum itself is really just a type - so it does not, in itself, occupy memory.

 

Only when you create a variable of that type does that variable occupy memory.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Then there is of-course the case of using a value of the type. Nothing different there performance-wise v/s comparing directly with eg an int.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dan Saks often writes wisely : http://www.embedded.com/electronics-blogs/programming-pointers/4023879/Enumeration-Constants-vs-Constant-Objects
EDIT: Note that the article is from 2001. While the principles still holds, the performance of compilers might have changed considerably.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Thu. Jun 8, 2017 - 08:26 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note that "const objects" is one of the places where 'C' does differ from C++ !

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I must have missed the memo. Why is an enum member a "better" choice than the more obvious "static const int foo = 10;" ?

 

(But I agree that either is better than a #define)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Isn't scoped enums even better (C++11 onwards)? Should at least remove the implicit cast between enum members and int.

 

EDIT; for someones enjoyment: cpp.sh

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

meolsen wrote:
EDIT; for someones enjoyment: cpp.sh
Not that enjoyable!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sure... can't convert enum class to int implicitly

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I asked about enums occupying memory, here is what I had in mind.

 

If I #define NextVal 10, then the only "memory" used is the same flash space that any numeric value would occupy. [nb: this statement is clearly true only for Harvard architectures where code occupies some nominally nonvolatile memory]

 

But, if I do

 

    enum   {
        NextVal = 10,
        };

What is the memory "footprint"? Does is live in SRAM? Is the memory footprint any different than

 

static const uint8_t NextVal = 10;

 

 If used in a place where speed is critical, aren't there usually more operations to get it out of SRAM than from FLASH (especially if it is a single byte would otherwise be embedded in the (AVR) instruction)?

 

And, again, folks, I am not in any way critical of the suggestions and comments above; they are really appreciated. Just trying to compare and contrast (and learn).

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Thu. Jun 8, 2017 - 03:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define NextVal 10

enum {
    NextVal = 10,
};

None of these occupy ANY memory.

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All of those are evaluated at compile-time?

 

OK, lets extend this a little. We know that

 

uint8_t MaxVal = 10;

Does not, all by itself, occupy memory. Memory occupancy is determined as it is used. But, the simple variable declaration, just shown, does occupy memory once you write

 

x = MaxVal;

And, in a Harvard architecture, that memory occupancy is SRAM rather than FLASH because MaxVal, here as a plain variable, can be altered at other points in the program. But, if I write

 

static const uint8_t NextVal = 10;

And use it thus:

 

x = MaxVal;

Does MaxVal live in SRAM or does it live in FLASH (again, Harvard architecture)? Is the "assignment" made at compile time (as a #define would be) or is it assigned at run time?  The same question, then, of an enum. If MaxVal had been defined as an enum, and used in an assignment statement, does that value live in SRAM or does it live in FLASH? If (and, of course, this is a big "if") speed and memory footprint are important at a given point in the program, it seems to me that this would be useful information.

 

HOWEVER, this thread started out about MISRA, static code analysis, and, by inference, "safety". We know that type checking is an important aspect of safety. On the other hand, safety can include constants being in FLASH where we have a very high confidence level that nothing will alter them (no buffer over-runs, no stack overflows, no nothing!). And, by "FLASH", I don't mean p-strings, but the way the AVR op-codes embeds constants into the opcodes, the results then being in FLASH.

 

So, please, I am not trying to be argumentative, here. Quite the contrary. Trying to learn!

 

Thanks for every one's input!

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Thu. Jun 8, 2017 - 04:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps some of the C experts hammer me down, but I remember it this way.

 

Because it's legal to make a pointer to a const, it has to live in RAM on an AVR.

 

add

You can't make a pointer to enum therefore it is different. 

 

 

Last Edited: Thu. Jun 8, 2017 - 05:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The case for using a name instead of a raw number is simple:
Documentation and the ease of making reliable changes.

 

Deciding between #define , static const int
and enum constants can be interesting.

 

@ka7ehk:
Unless MaxVal is global, the as-if rule allows the
compiler to do with MaxVal pretty much whatever it wants.
Even without help, the compiler will probably be
able to figure out whether MaxVal is ever changed.
If never changed, (uint8_t)10 will be quietly substituted for MaxVal.
MaxVal might be as-if-ed completely away.
Do not make a pointer to it.
x=MaxVal will probably become LDI Rx, 10 .
In C, no object may be used as the dimension of a global array.
In C++, your static const uint_t NextVal may be so used.
NextVal will almost certainly be as-if-ed away.
The necessary reasoning is required to allow its use as an array size.

 

Deciding between #define , static const int
and enum constants is not always interesting.

 

If you just want one number in the range -0x7FFF..0x7FFF
and do not need it in a constant expression,
use whatever makes you feel good.
If you need it for a constant expression, e.g. an array dimension,
in C, scratch static const int.
If you need a built-in type, scratch enum.
If you need it in assembly, use #define.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:

 

In C, IIRC the types of the enum constants are int (!!)
and sizeof(enum menage) == sizeof(int) .

Not sure about C++.

 

GNU has always had, since I've used it, the -fshort-enums compiler option.  This causes enums to have the smallest int that can contain the enumerated values.  In my code that is almost invariably an 8 bit int.

 

In the latest GNU and Microsoft C++ compilers, you can specify the size of the enums.  I don't know about C compilers.

 

   enum   Events : unsigned char  {
      None = 0,
      };
 

 

Last Edited: Thu. Jun 8, 2017 - 07:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C++ now allows one to specify the underlying type of an enumeration type.

For C, IIRC, the underlying type is always int.

Optimization usually handles size issues with enumerators.

It's not much of an issue, except for arrays of enumeration variables.

Making such arrays arrays of bytes (not enums) will sidestep the size issue.

C's enums do not help much with type safety..

ints and C's enums can be implicitly converted to each other.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PC-lint

PC-lint Plus is multi-platform instead of Windows only (now: Linux 64b, macOS, Windows) along with numerous improvements.

Gimpel Software

Gimpel Software

http://www.gimpel.com/html/index.htm

PC-lint Plus is Now Available

...

 

What is PC-lint Plus?

PC-lint Plus is a rewrite of PC-lint from the ground up. ...

...

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Over time we have used various other static code analysis tools (including cppcheck - which is both C and C++ despite the name) but these days we use the terror that is Klockwork:

Electronic Design

Electronic Design

Improving Code Quality in the New Year

Are you going to reduce bugs and improve security and code quality in 2018?

William Wong | Dec 21, 2017

http://www.electronicdesign.com/industrial-automation/improving-code-quality-new-year

...

There are a number of vendors that provide static analysis tools, including AdacoreRogue Wave Software/KlockworkGrammatechLDRAParasoftProgramming Research, and Synopsys. There are also some open-source tools, including cppcheck and the Eclipse Codan (CODe Analysis) project

...

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SonarQube

Continuous Code Quality

https://www.sonarqube.org/

FOSS with value-added by commercial offerings.

 

https://github.com/SonarSource

SonarQube due to :

FastArduino

https://github.com/jfpoilpret/fast-arduino-lib#fastarduino

...

FastArduino C++ code is also analyzed by SonarQube and results of this analysis are published from time to time here.

...

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
 (klocwork in particular would produce a lot of "false positives" in our codebase.  That had to be approved and added to exception lists. :-( )

Electronic Design

What's the Difference Between Sound and Unsound Static Analysis?

by Claire Dross [AdaCore, SPARK], Boris Yakobowski [AdaCore, CodePeer]

Sep 12, 2018

https://www.electronicdesign.com/embedded-revolution/whats-difference-between-sound-and-unsound-static-analysis

...

[in 3rd and 4th paragraphs]

In practice, sound static analyzers output an exhaustive list of places where the vulnerability could occur, most of which are false alarms or "false positives" that need to be reviewed.

While more demanding for users, these static analyzers make it possible to achieve higher levels of confidence than is possible with their unsound counterparts, which makes them attractive in a security context. 

...

 

Definition of Sound Analysis

...

 

Costs and Benefits of Sound and Unsound Analysis

[first paragraph, bullets, second paragraph]

Depending on the technique used, they [sound analyses] may require code changes, user-supplied annotations, or reviews of numerous false alarms.

[remainder is on SPARK]

 

Conclusion

...

[last paragraph]

Thanks to its ease of deployment, unsound static analysis has become a standard tool in serious software development. It’s used in most large software companies, and advised by best practices. Due to its higher cost, sound static analysis has long been the domain of experts. However, with the recent progress in verification techniques, sound static analysis is used in more and more projects, and is becoming part of the standard development process when strong safety or security requirements are needed. In the years to come, sound static analysis may become a standard tool for critical software development.

 

P.S.

[end of second paragraph]

For example, Mozilla uses Clang Analyzer, clang-tidy, their own checkers, and Coverity on its C/C++ code.2

Extra Clang Tools 8 documentation

Clang-Tidy

http://clang.llvm.org/extra/clang-tidy/

...

 

clang-tidy is a clang-based C++ “linter” tool. Its purpose is to provide an extensible framework for diagnosing and fixing typical programming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis. clang-tidy is modular and provides a convenient interface for writing new checks.

 

...

 

Edit: missing URL

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Wed. Sep 26, 2018 - 03:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
The application where this might apply is a "public infrastructure" one.
One instance of infrastructure are railroads; the rail industry has safety standards.

Implementing what's required per a safety standard is one of the Big 5 best practices.

 

Barr Group

Firmware Update v18.03

by Michael Barr

2018-03-13

https://barrgroup.com/resources/firmware-update/v1803

(about mid-page)

The State of Embedded Systems Safety

[safety standard, coding standard, code reviews, static analysis, regression testing]

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

el_programmer wrote:
Speaking about the MISRA rules, some analyzers check the compliance of the code with these standards (Coverity, Klocwork, Parasoft and others), and some - like PVS-Studio don’t. As the developers state in their blog ...
MISRA added to PVS-Studio as blog'd on 10.12.2018 in addition to CWE and SEI CERT :

PVS-Studio: Support of MISRA C and MISRA C++ Coding Standards

by Andrey Karpov (CTO, Program Verification Systems)

...

So initially we have been critical to the MISRA standards and haven't planned to introduce them for a long time.

...

Everything changed when in 2018 we've started supporting embedded systems. This year we supported the following features in the analyzer:

  • Windows. IAR Embedded Workbench, C/C++ Compiler for ARM C, C++
  • Windows/Linux. Keil µVision, DS-MDK, ARM Compiler 5/6 C, C++
  • Windows/Linux. Texas Instruments Code Composer Studio, ARM Code Generation Tools C, C++
  • Windows/Linux/macOS. GNU Arm Embedded Toolchain, Arm Embedded GCC compiler, C, C++

...

So now you can install or upgrade PVS-Studio and start using diagnostics based on rules from MISRA C and MISRA C++. The set of supported rules is incomplete, but it shouldn't be an obstacle to start using PVS-Studio. 

...

[how to enable MISRA in PVS-Studio on Windows, macOS, and Linux]

...

 

P.S.

[how to for feedback]

...

 

PVS-Studio is now zero price for conditional FOSS (specific repositories, no mirrors) and conditional non-FOSS (ones as given (iow an individual) or in the specific role of student, specific comments in non-header source code files)

Free PVS-Studio for those who develops open source projects

 

edit: by-line

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Sat. Dec 29, 2018 - 10:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A zero price instance of IAR C-STAT :

The Embedded Muse 365 - This Week's Cool Product

...

Need development tools? IAR's suite is provided along with their runtime analysis tools.

...

"Also included for free is C-STAT and C-RUN for code analysis, which is normally a separate purchase from IAR."

...

IAR Embedded Workbench® for Renesas Synergy™ (Windows 7, Windows 10)

 

Edit: 2nd URL

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Thu. Jan 10, 2019 - 08:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ways to Get a Free PVS-Studio License

by Andrey Karpov

March 11, 2019

...

Open source projects, small closed projects, public security specialists and owners of the Microsoft MVP status can use the license for free.

...

 

"Dare to be naïve." - Buckminster Fuller