﻿# Search of 64\-bit errors in array implementation

In PVS\-Studio 3\.43, we revised the way how Viva64 analyzer detects errors in the classes serving as containers \(arrays\)\. Before, we have stuck to the principle that if a class has operator\[\], its parameter must have memsize\-type \(ptrdiff\_t, size\_t\) and not int or unsigned\. We still recommend that you use memsize type as an argument for operator\[\]\. It allows the compiler to build a more efficient code in some cases and avoid some 64\-bit errors beforehand\. Now we have changed the approach to working with classes that have operator\[\] what allows us to reduce the number of unnecessary diagnostic warnings\.

Let us consider an example that might contain an error if we want to work with large data amounts:

```cpp
class MyArray {
  std::vector <float> m_arr;
  ...
  float &operator[](int i)
  {
    return m_arr[i];
  }
} A;
...
int x = 2000;
int y = 2000;
int z = 2000;
A[x * y * z] = 33;
```

The first drawback of this code is that _operator\[\]_ does not allow us to access the item with the number more than _INT\_MAX_\.

Note\. I would like to clarify one important thing\. In the release\-version, for a code like the one in the example, the compiler can provide an optimization that will work because the 64\-bit register will be used to calculate and pass the index\. I will make a separate post to examine this example more thoroughly\. But this luck does not make the code correct\. You may learn more about dangerous optimizations [here](https://pvs-studio.com/en/blog/posts/cpp/a0043/)\.

The second drawback of the code lies in the expression _x\*y\*z_ where an overflow might occur when working with a large array\.

Before, the analyzer has generated two warnings \([V108](https://pvs-studio.com/en/docs/warnings/v108/)\)\. The first is using _int_ type when calling the array _m\_arr_\. The second is using _int_ type when calling the array A\. Although _operator\[\]_ of the class _MyArray_ takes an _int_ argument, we offered to use a memsize\-type as the index\. When the programmer changed the types of the variables _x_, _y_ and _z_ to _ptrdiff\_t_, Visual C\+\+ compiler started warning about type conversion in the line _A\[x \* y \* z\] \= 33_:

warning C4244: 'argument' : conversion from 'ptrdiff\_t' to 'int', possible loss of data

This warning prompted the user to change the argument in _operator\[\]_ and the code became absolutely correct\. Here is an example of the corrected code:

```cpp
class MyArray {
  std::vector <float> m_arr;
  ...
  float &operator[](ptrdiff_t i)
  {
    return m_arr[i];
  }
} A;
...
ptrdiff_t x = 2000;
ptrdiff_t y = 2000;
ptrdiff_t z = 2000;
A[x * y * z] = 33;
```

Unfortunately, this diagnosis approach has one great drawback\. In some cases, _operator\[\]_ cannot be changed or using _int_ as the index is absolutely justified\. And it appeared that Viva64 analyzer generated a lot of unnecessary warnings\. _CString_ class from MFC can serve as an example\. The operator in _CString_ class has the prototype:

```cpp
TCHAR operator []( int nIndex ) const;
```

Because of this the code is diagnosed as dangerous:

```cpp
int i = x;
CString s = y;
TCHAR c = s[i];
```

_CString_ class is inaccessible to edit\. And, well, hardly will anyone use _CString_ type in a standard program to work with lines longer than two milliard characters\. In its turn, Viva64 analyzer generated many warnings on this code\. If the programmer changed the index's type from _int_ to _ptrdiff\_t_, it was the compiler that generated the warnings\. We could use warning suppression //\-V108, but it would overload the code\. You may learn more about warning suppression in the article: PVS\-Studio: using the function "[Mark as False Alarm](https://pvs-studio.com/en/docs/manual/0017/)"\.

We made a decision to consider the construct _A\[x \* y \* z\] \= 33;_ from the first example safe\. Now, if _operator\[\]_ takes a 32\-bit type as an argument \(for example, _int_\) and we call this operator also using a 32\-bit type, this call is considered safe\.

Of course, it might hide an error\. That is why, we added a new diagnostic warning [V302](https://pvs-studio.com/en/docs/warnings/v302/): "Member operator\[\] of 'FOO' class has a 32\-bit type argument\. Use memsize\-type here"\. This diagnostic warning is generated for _operator\[\]_ defined with a 32\-bit argument\.

The smartness of this solution consists in that this warning is not generated on the library code that is not accessible to change\. I\.e\., V302 warning will not be generated for the class _CString_ but will be for the user class _MyArray_\.

If _operator\[\]_ in _MyArray_ class is correct and really should have the type _int_, the programmer will only need to write only one warning suppression //\-V302 in this class instead of multiple places where it is used\.

The last change related to array processing concerns introduction of one more warning V120: "Member operator\[\] of object 'FOO' declared with 32\-bit type argument, but called with memsize type argument"\. In whole, this warning copies the compiler warning about converting a 64\-bit type to a 32\-bit one\. It will be useful when there are a lot of warnings generated by the compiler and among them you miss the information about code efficiency on a 64\-bit system\.