OOO “Program Verification Systems” (Co Ltd)
www.viva64.com
The PVS-Studio tool
◦ the Viva64 rule set for 64-bit software analysis;
◦ the VivaMP rule set for parallel software analysis;
◦ the general-purpose analysis rule set.
Licensing and pricing policy for
PVS-Studio
About the OOO “Program Verification Systems”
company
Analysis of C/C++ source code
PVS-Studio is a static code analyzer intended for
developers of contemporary resource-intensive
software
PVS-Studio includes three sets of diagnostic rules:
1. Viva64 intended for detecting errors of 64-bit
software development and migration;
2. VivaMP intended for detecting parallel issues in
source code of software developed with the
OpenMP technology;
3. General-purpose analysis for detecting general
errors such as misprints, buffer overflows,
condition errors, etc.
errors accompanying porting of 32-bit software to 64-bit systems;
errors accompanying development of new 64-bit software;
errors in parallel applications caused by programmers’ insufficient knowledge of the
OpenMP technology;
errors caused by incorrect memory handling in parallel code (unprotected memory
access, absence of synchronization, incorrect variable access mode and so on);
logical errors, incorrect use of algorithms and containers, buffer overflows;
misprints brought into the text during copying of code fragments or through inattention;
non-optimal constructs that can be easily optimized.
develop new 64-bit software;
port 32-bit code to 64-bit systems;
provide software with support of concurrent execution
using the OpenMP technology;
want to enhance code’s quality and safety;
want to detect as many errors as possible already at
the stage of developing.
Easy-to-download:
◦ http://www.viva64.com/en/pvs-studio-download/
Easy-to-try:
◦ PVS-Studio integrates into Visual Studio;
◦ The distribution package includes samples of software with
errors.
Easy-to-buy (online or through a bank):
◦ http://www.viva64.com/en/order/
integration into Visual Studio 2005/2008/2010;
C and C++ support;
C++0x support within the framework of Visual Studio 2010;
detailed help system (including the Russian language);
usability;
convenient error filtering and suppression system;
analysis of files in concurrent mode.
Some our customers
www.viva64.com/en/customers/
The problem of applications migration to
64-bit platforms
• The process of code migration is inevitable.
• C/C++ applications migration is most difficult because of
language peculiarities.
• During migration, there can occur errors in programs which
are impossible to diagnose by the existing methodology of
testing.
• It is difficult to get assured in the correctness of modern
programs after their migration to 64-bit systems (MS-DOS 1.0
contained 4,000 code lines, while Windows Vista contains
50,000,000). That is why it is impossible to refer to the
experience of past migrations.
100
90
80
70
60
50
40
30
20
10
0
Pure Managed
(Visual Basic, C#)
Unsafe Managed
COM
P/Invoke (C#+C++)
MC++ / C++
According to Kang Su Gatlin, Visual C++ Program Manager,
Microsoft Corporation, 2004
Here are some samples of errors
Viva64 can detect
Base class:
class CWinApp {
virtual void WinHelp(DWORD_PTR, UINT);
};
User’s code:
class CMyApp : public CWinApp {
virtual void WinHelp(DWORD, UINT);
};
32-bit system:
64-bit system:
int A = -2;
unsigned B = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (A + B);
printf("%i\n", *ptr);
Variable A type int is cast to type unsigned;
A and B addition is carried out. As a result, we obtain value 0xFFFFFFFF type unsigned;
Expression "ptr + 0xFFFFFFFFu“ is calculated. The result depends on pointer dimension
on the given platform. In a 32-bit program, the expression will be equivalent to "ptr - 1"
and we will successfully print number 3. In a 64-bit program, value 0xFFFFFFFFu will be
added to the pointer, as a result, the pointer will appear far beyond the array limits.
bool IsPresent(char *array, size_t arraySize,
char key)
{
for (unsigned i = 0; i != arraySize; ++i)
if (array[i] == key)
return true;
return false;
}
This code will lead to an infinite loop occurrence if arraySize exceeds value UINT_MAX.
Detection of such errors using unit-tests or dynamic analyzers (BoundsChecker) is extremely
complicated by the necessity of running on large data sizes. During processing of a small data
size, the error will not be detected.
ptrdiff_t SetBitN(ptrdiff_t value, unsigned bitNum) {
ptrdiff_t mask = 1 << bitNum;
Code of the given bit setting in unit.
return value | mask;
}
The first error consists in character variable
shift. During 31st bit setting on a 64-bit
system, the result of the function
operation will be the value
0xffffffff80000000
The second error is connected with the
fact that this code will never set bits with
numbers 32 to 63. Please note that "1" has
type int, and during shift by 32 positions,
overflow will occur. Whether we obtain as
a result 0 (A) or 1 (B) depends on the
compiler implementation.
#define N_COUNT 100
int **pArray = (int**)
malloc(N_COUNT * 4);
hFileMapping = CreateFileMapping (
(HANDLE) 0xFFFFFFFF,
NULL,
PAGE_READWRITE,
(DWORD) 0,
(DWORD) (szBufIm),
(LPCTSTR) &FileShareNameMap[0]);
size_t n, newexp;
n = n >> (32 - newexp);
The most widespread magic values which
are dangerous during applications porting
from a 32-bit to a 64-bit platform
ptrdiff_t UnsafeCalcIndex(int x, int y, int width) {
return x + y * width;
}
...
int domainWidth = 50000;
int domainHeght = 50000;
for (int x = 0; x != domainWidth; ++x)
for (int y = 0; y != domainHeght; ++y)
array[UnsafeCalcIndex(x, y, domainWidth)] = 1;
This code cannot fill correctly the array, which consists of
50000*50000 elements. During calculation of the expression "x
+ y * width" overflow occurs, and, as a result, outbounds the
array limits.
size_t __fread(void * __restrict buf, size_t size, size_t count,
FILE * __restrict fp);
size_t fread(void * __restrict buf, size_t size, size_t count,
FILE * __restrict fp)
{
int ret;
FLOCKFILE(fp);
ret = __fread(buf, size, count, fp);
FUNLOCKFILE(fp);
return (ret);
}
Function __fread returns type size_t, however, for storing the quantity of read bytes,
type int is used. As a result, in case of large sizes of the data being read, the function
can return the wrong quantity of bytes which will be read in fact.
Patterns of 64-bit errors in the code were explored in more than 100 various
articles in printed and electronic media.
Our own experience in computational modeling packages code migration and
visualization in C++ was considered.
During the research, a base consisting of dozens of various error patterns
connected with code migration to 64-bit systems was created. Both wellknown (published) errors and earlier unknown errors were included in the
base.
Rules of diagnostics were formulated on the basis of detected error patterns.
Both error patterns and diagnostic rules are published in our articles and are
available to everyone.
The table presents comparison carried out at the end of
2008. Nowadays, PVS-Studio has much more capabilities.
E.G.S. S.r.l. Company is engaged in the development
of solutions in the sphere of 3D objects modeling on
the basis of triangulated grids.
The total size of Leios Studio source code is 13 megabytes
(440,000 code lines).
Code migration with the use of Viva64 allowed to save much
time which would be needed in case of manual code review.
The main problem cases detected in the process of automatic
code analysis with the help of Viva64 tool are:
◦ Computational algorithms features during processing of large data
volumes;
◦ Work with large size files;
◦ Processing of 3d-models containing large number of triangles (the
larger the number of triangles is, the more precise the models are);
◦ Work of licensing subsystem;
Details: http://www.viva64.com/en/a/0036/
http://loki-lib.sourceforge.net
Project size:
1.5Mb, 125 files
Potentially dangerous
constructions detected with
the help of Viva64: 89
Of which real errors: 6
Details: http://www.viva64.com/en/a/0049/
Absence of keywords in directives
Incorrect operating with locking
Dependence of code behavior on the quantity of threads
processing it
Simultaneous work with common resource
Vulnerable access to common memory
Careless use of local variables
Unnecessary memory protection from simultaneous writing
Performance errors
Here are some samples of errors
VivaMP can detect
#pragma omp parallel for
for (size_t i = 0; i != n; ++i) {
float *array = new float[10000];
delete [] array;
}
The example will lead to incorrect behavior of the program and most likely to its abnormal
termination, if memory allotment error occurs.
The error is related to the exception throwing from the parallel section. According to
OpenMP specification, if you use exceptions inside a parallel section, all these exceptions
should be processed inside this section. If you use operator new inside a parallel section,
you should consider seizing the exception which, according to C++ language standard will
be generated at memory allotment error.
void Foo() {
#pragma omp for
for (int i = 0; I < n; ++i)
…
}
#pragma single
{
…
}
#pragma omp parallel
{
omp_set_num_threads(2);
…
}
Despite the developer’s expectations, the loop will run in
one thread only.
Directive omp forgotten. Though VC++ compiler will give the
message "warning C4068: unknown pragma", this warning
can be ignored in big difficult projects or can be disabled at
all.
The number of threads cannot be redefined inside a parallel
section. This leads to an error during program running and
its abnormal termination.
int a = 0;
#pragma omp parallel for num_threads(4)
for (int i = 0; i < 100000; i++) {
a++;
}
Race condition happens when several threads of a multithread application attempt to
simultaneously gain access to data, with that, at least one thread is making a record. Race
conditions can lead to unpredictable results, and they are often hard to detect.
Sometimes, race conditions consequences show only after a long period of time in quite
another part of the application. Moreover, errors of such kind are extremely difficult to
duplicate.
It is extremely effective to detect at least some of such errors with the help of static
analysis as early as at the code writing stage.
pragma omp parallel
{
static int st =
Calc();
...
}
The static variable will start the process of
initialization in several threads at once, this can lead
to an uncertain result. The troubles of such errors
consist in their unstable and rare manifestation
during testing.
Correlation of the cost on eliminating defects depending on the time they were
introduced and found. The data for the table were taken from the book “Code
complete” by S. Macconnell.
It is not crucial how complicated an error is: whether this is a mere
misprint or error of algorithm’s logic. It is very beneficial to detect at
least a part of such errors already at the stage of coding. It
significantly reduces costs on code testing and maintenance.
The PVS-Studio analyzer diagnoses a lot of diverse types of errors. We
cannot enumerate all the types of errors it can detect, so please refer
to the documentation for the list of provided diagnoses.
Documentation (online): http://www.viva64.com/en/d/
Here are samples of errors the
general-purpose analyzer can detect
int iChilds[2];
...
bool hasChilds() const { return(iChilds > 0 || iChilds > 0); }
Although this code successfully compiles without any warnings, it is
meaningless in this case. The correct code must look as follows:
int iChilds[2];
...
bool hasChilds() const { return(iChilds[0] > 0 || iChilds[1] > 0); }
struct CVariable {
char name[64];
};
void CRendererContext::RiGeometryV(int n, char *tokens[]) {
for (i=0; i<n; i++) {
CVariable var;
if (parseVariable(&var, NULL, tokens[i]))
tokens[i] = var.name;
}
The pointer to an array located in a variable of the
}
CVariable type is saved in an external array. As a
result, the "tokens" array will contain pointers to
already non-existent objects as the RiGeometryV
function terminates.
MD5Context *ctx;
...
memset(ctx, 0, sizeof(ctx));
The misprint here causes the structure to be cleared only partially. The error
in this code is that it is the size of the pointer which is calculated instead of
the MD5Context structure’s size. This is the correct code:
MD5Context *ctx;
...
memset(ctx, 0, sizeof(*ctx));
if (a == 1)
Foo1();
else if (a == 2)
Foo2();
else if (a == 1)
Foo3();
The 'Foo3()' function will never get control.
CSize(POINT pt) { cx = pt.x; cx = pt.y; }
The code is taken from a real application where the programmer
implemented his own class CSize. The correct code certainly must have
looked this way:
CSize(POINT pt) { cx = pt.x; cy = pt.y; }
for (i = 0; i < n; i++);
{
Foo(i);
}
void unregisterThread() {
Guard<TaskQueue> g(_taskQueue);
std::remove(_threads.begin(),
_threads.end(),
ThreadImpl::current());
}
The std::remove function does not remove the items from the container. It
only shifts the items and returns the iterator to the beginning of the trash.
Assume we have the vector<int> container that contains items
1,2,3,1,2,3,1,2,3. If we execute the code "remove( v.begin(), v.end(), 2 )", the
container will contain items 1,3,1,3,?,?,? where ? is some trash. Also, the
function will return the iterator to the first trash item, so if we want to
remove these trash items, we must write the following code:
"v.erase(remove(v.begin(), v.end(), 2), v.end())".
License Type
Price
PVS-Studio - Single User License
€1600
PVS-Studio – Team License
€3500
PVS-Studio – Site License
see
on site
Order Page: http://www.viva64.com/en/order/
You are enabled to get new versions (including majorversions) during 1 year;
You are enabled to get support by e-mail during 1 year;
You get time unbounded right to use the program. A
year after you purchased it, you can continue getting
new versions of PVS-Studio and contacting the support
service. Restrictions will only concern new diagnostic
capabilities that will appear in the analyzer after your
license has expired.
The certificate of official registration of
computer programs N2007614164,
"Viva64". Registered in Computer Program
Register on September 28th, 2007.
The certificate of official registration of
computer programs N2008610480,
"VivaCore, a source code analysis library".
Registered in Computer Program Register
on January 25th, 2008.
The certificate of official registration of
computer programs N2008612845,
"Viva64 2.0". Registered in Computer
Program Register on May 29th, 2008.
Intellectual property is registered
Our articles are published at largest sites
for developers
http://www.viva64.com/en/experience/
Common information on working with the PVS-Studio analyzer
http://www.viva64.com/en/d/0011/
A Collection of Examples of 64-bit Errors in Real Programs
http://www.viva64.com/en/a/0065/
32 OpenMP Traps For C++ Developers
http://www.viva64.com/en/a/0054/
You can find other articles on 64-bit and parallel programs, as
well as on technology of code analysis, at:
http://www.viva64.com/en/articles/
OOO “Program Verification Systems” (Co Ltd)
300027, Russia, Tula, Metallurgov 70-1-88.
Web: www.viva64.com
E-mail: [email protected]
Phone: +7 (4872) 38-59-95
Working time: 09:00 – 18:00 (GMT +3:00)
© Copyright 2026 Paperzz