
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] ) {
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] ) {
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++ ) {
will compile and will work correctly.
In addition to explicitly specifying
sizeof (smth) / sizeof (smth [0]), they also use macros:
Let's see how the new warning works in these cases. We will
try on
gcc.godbolt.orgFirst, 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++ ) {
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++ ) {
The overwriting code also gives a warning (we use a portable
memset () for demonstration only):
void somethingMemset( char key[9000] ) {
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