V106. Implicit type conversion N argument of function 'foo' to memsize type.


The analyzer found a possible error related to the implicit actual function argument conversion to memsize type.

The first example.

The program deals with large arrays using container CArray from library MFC. On the 64-bit platform the number of array items may excess the value INT_MAX (2Gb), which will make the work of the following code impossible:

CArray<int, int> myArray;
...
int invalidIndex = 0;
INT_PTR validIndex = 0;
while (validIndex != myArray.GetSize()) {
  myArray.SetAt(invalidIndex, 123);
  ++invalidIndex;
  ++validIndex;
}

The given code fills all the array myArray items with value 123. It seems to be absolutely correct and the compiler won't show any warnings in spite of its impossibility to work on the 64-bit platform. The error consists in the use of type int as an index of the variable invalidIndex. When the value of the variable invalidIndex excesses INT_MAX an overflow will occur and it will receive value "-1". The analyzer diagnoses this error and warns that the implicit conversion of the first argument of the function SetAt to memsize type (here it is type INT_PTR) occurs. When seeing such a warning you may correct the error replacing int type with a more appropriate one.

The given example is significant because it is rather unfair to blame a programmer for the ineffective code. The reason is that GetAt function in class CArray in the previous MFC library version was declared as follows:

void SetAt(int nIndex, ARG_TYPE newElement);

And in the new version:

void SetAt(INT_PTR nIndex, ARG_TYPE newElement);

Even the Microsoft developers creating MFC could not take into account all the possible consequences of the use of int type for indexing in the array and we can forgive the common developer who has written this code.

Here is the correct variant:

...
INT_PTR  invalidIndex = 0;
INT_PTR validIndex = 0;
while (validIndex != myArray.GetSize()) {
  myArray.SetAt(invalidIndex, 123);
  ++invalidIndex;
  ++validIndex;
}

The second example.

The program determines the necessary data array size and then allocated it using function malloc as follows:

unsigned GetArraySize();
...
unsigned size = GetArraySize();
void *p = malloc(size);

The analyzer will warn about the line void *p = malloc(size);. Looking through the definition of function malloc we will see that its formal argument assigning the size of the allocated memory is represented by type size_t. But in the program the variable size of unsigned type is used as the actual argument. If your program on the 64-bit platform needs an array more than UINT_MAX bytes (4Gb), we can be sure that the given code is incorrect for type unsigned cannot keep a value more than UINT_MAX. The program correction consists in changing the types of the variables and functions used in the determination of the data array size. In the given example we should replace unsigned type with one of memsize types, and also if it is necessary modify the function GetArraySize code.

...
size_t  GetArraySize();
...
size_t size = GetArraySize();
void *p = malloc(size);

The analyzer show warnings on the implicit type conversion only if it may cause an error during program port on the 64-bit platform. Here it is the code which contains the implicit type conversion but does not cause errors:

void MyFoo(SSIZE_T index);
...
char c = 'z';
MyFoo(0);
MyFoo(c);

If you are sure that the implicit type conversion of the actual function argument is absolutely correct you may use the explicit type conversion to suppress the analyzer's warnings as follows:

typedef size_t TYear;
void MyFoo(TYear year);
int year;
...
MyFoo(static_cast<TYear>(year));

Sometimes the explicit type conversion may hide an error. In this case you may use the V201.

Additional materials on this topic:


Do you make errors in the code?

Check your code
with PVS-Studio

Static code analysis
for C, C++ and C#

goto PVS-Studio;