📜 ⬆️ ⬇️

New warning about incorrect calculation of the size of the array in gcc 5.1

The good news for gcc users is that when using gcc 5.1 and higher, it will be easier for them to quickly find such a common error in calculating the size of an array declared as a function parameter:

void something( char arr[100] ) { // this loop is broken for( size_t index = 0; index < sizeof(arr)/sizeof(arr[0]); index++ ) { //WHATEVER } } 

Although the parameter is declared as an array of a known size, from the point of view of the C and C ++ compilers, this is a char * type pointer, so sizeof (arr) will give the same value as sizeof (char *) - most likely 4 or 8. The loop is rather all, will not work as expected.
Another variant:
 void something( char encryptionKey[9000] ) { // WHATEVER, PROFIT // this call is broken SecureZeroMemory( encryptionKey, sizeof(encryptionKey)); // erase the key } 

here, the developers wanted to overwrite any data with zeros , but because of an error, only the first few bytes will be overwritten. Such an error is more difficult to find by testing than the first.

To find such a code, it was easier, in gcc 5.1 and newer, such a code gives a warning and is enabled by default.
')
Some readers are already in a hurry to comment on the curvature of the hands of the authors of the code from the examples above. However, the problem is so common that in C ++ code it is recommended to use the following focus ( from here ) with the template function:

 template<typename StoredType, size_t Size> char ( &ArrayElementsCountHelper(StoredType( &Array )[Size]) )[Size]; #define countOfElements(Array) sizeof(ArrayElementsCountHelper (Array)) 

Using countOfElements () in the code above will result in a compilation error, but this code:

 char arr[100] for( size_t index = 0; index < countOfElements(arr); index++ ) { //WHATEVER } 

will compile and will work correctly.

In addition to explicitly specifying sizeof (smth) / sizeof (smth [0]), they also use macros:

 // in a header far, far away... #define errorProneCountOfElements( arr ) (sizeof(arr)/sizeof((arr)[0])) for( size_t index = 0; index < errorProneCountOfElements (arr); index++ ) { //WHATEVER } 

Let's see how the new warning works in these cases. We will try on gcc.godbolt.org

First, we select gcc 4.9.2 as the compiler - with the default settings, warnings about incorrect size calculations will not be in any of the examples. Then we will change to gcc 5.1.0 - in the examples with the cycle we get the string with the header of the cycle

warning: 'sizeof' on array function parameter 'arr' will return size of 'char *' [-Wsizeof-array-argument]

In this code:
 void somethingExplicitCount( char arr[] ) { for( size_t index = 0; index < sizeof(arr)/sizeof(arr[0]); index++ ) { //WHATEVER } } 

issued the same warning. Similarly in the code with the macro:
 void somethingMacroCount( char arr[9000] ) { for( size_t index = 0; index < errorProneCountOfElements(arr); index++ ) { //WHATEVER, PROFIT } } 

The overwriting code also gives a warning (we use a portable memset () for demonstration only):
 void somethingMemset( char key[9000] ) { //WHATEVER, PROFIT memset(key, 0, sizeof(key)); // don't use memset for sensitive data } 

PROFIT.

Special attention is given to the fact that clang version 3.0 was already able to issue the same warning. LLVM once said that this is a clang-specific warning and gcc does not know how. NO MOAR.

The warning is enabled by default, developers will only have to correct the problem code correctly.

Dmitry Mescheryakov,
product department for developers

Source: https://habr.com/ru/post/263609/


All Articles