-Warray-bounds option to GCC compiler

What exactly is the -Warray-bounds option to the GCC compiler supposed to warn about?
the man page states:

~ g++ --version
g++ (GCC) 7.3.1 20180130 (Red Hat 7.3.1-2)
Copyright (C) 2017 Free Software Foundation, Inc.

Thank you.

I am not sure about how basic you need an explanation because the man page is pretty self-explanatory. So just give me some feedback if this doesn't make you get it:

Consider a "normal" variable first: a variable is of a certain data type and hence represents a certain amount of (allocated) memory somewhere in RAM. I.e. when you write a declaration like:

int myvar

then the compiler sets aside a certain amount of bytes (depends on how "int" is defined, but nowadays usually 4 bytes ^= 32 bits) and you can address this 4-byte space by using the name "myvar".

Now arrays: arrays are basically lists of elements where each element is a variable like above. If you i.e. create an array of 7 elements of the type int the compiler will set aside the same 4 bytes as above - not once but seven times. These seven 4-byte-spaces will be placed one after the other. If you now adress the third element with some operation the compiler "knows" that the elements are 4-byte-blocks and therefore will translate that to byte 9-12 following the base address.

So far so good, but what would happen if you would request the eighth element, hmm? If the compiler doesn't "remember" that your element only has seven elements it would eventually give you the content of byte 29-32 - which holds some other data! What would happen if you'd requested the -2nd element? You might get data which aren't even part of the program (but maybe some OS data!).

These method of accessing array elements which don't even exist have been used historically to get access to memory parts the program would normally not have access to. Modern OSes have all sorts of security measures to make this impossible, but you can still accidentally access (and hence modify) your own program in memory for some probably unwanted effects.

To avoid this there is bounds checking: basically it is the complier making sure whatever array elements you access are being defined before.

I hope this helps.

bakunin

1 Like

bakunin,
Thanks for the explanation. I know what array bounds checking means. That's why I posted this question. Have you tried turning on the -Warray-bounds on GCC and accessing an illegal array position to see if it works as you described? I was expecting the compiler will give me warning for accessing an array element beyond its declared size, but it didn't give me any warnings at all. The below program runs just fine on my Linux box. I gave the gcc version on my post above. If I assign 10000 to index, program give segmentation fault, but still compiles with no warnings. -Warray-bounds switch is on.

int main()
{
	const int index=1000;
	int numbers[8] = {1,2,3,4,5,6,7,8};

	numbers[index] = 999;
	cout << numbers[index] << endl;

	return 0;
}

What level of optimization are you using?

Try at least level -O2 and it will probably catch it. Without at least that level the compiler doesn't do enough work to detect out-of-bounds but it should still detect it at run-time.

OK, now i understand better what your question is about. For reference i modified your program this way:

#include <iostream>
using namespace std;

int main()
{
        const int index=1000;
        int numbers[8] = {1,2,3,4,5,6,7,8};

        numbers[index] = 999;
        cout << numbers[index] << endl;

        return 0;
}

and used this compiler version:

# g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.6) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.

with the same results.

The problem IMHO is a misunderstanding of runtime-bounds-checking and compile-time bounds-checking. Runtime bounds-checking is included in the frontend (if at all) and this is only done for C but not for C++ according to this source. The link also mentions other options (mudflap, MIRO, valgrind, ...), which i haven't tested at all (i haven't programmed anything worthwhile in a HLL for a long time).

As far as i have understood the GNU compiler suite allows for switching on runtime bounds-checking, which the C-frontend does provide but the g++-frontend does not.

None of the frontends do compile-time bounds-checking (which you seem to be after) and, frankly, i doubt this is possible to do in a general way. The compiler would have to guess at compile-time which values any expression could evaluate to, which not only would need arbitrary computing time but also would need to decide the "Entscheidungsproblem - Wikipedia", which is proven to be undecidable (see also "halting problem in Turing-machines").

I hope this helps.

bakunin

1 Like

Hi,
I turned on -O2 on linux fedora (g++ GCC 7.3.1 20180130 Red Hat 7.3.1-2) and also tried the same code on a FreeBSD unix (g++ FreeBSD Ports Collection 6.4.0) and they both didn't catch the array out-of-bounds when both -O2 and -Warray-bounds=2 are enabled.

~ alias g++                                                                                                                                                              
alias g++='g++ -O2 -Wall -Wextra -Wchkp -Wmissing-include-dirs -Wswitch-default -Wunused \
  -Wduplicated-branches -Wduplicated-cond -Wshadow -Wpointer-arith -Wundef -Wunused-macros \
  -Wcast-qual -Wzero-as-null-pointer-constant -Wparentheses -Wuseless-cast -Wsign-conversion \
  -Wlogical-op -Wredundant-decls -Wrestrict -Winvalid-pch -Warray-bounds=2'
~ g++ t2.cpp && a.out 
999

I'm disappointed at that. Have you tried -O3?

Have you seen this:
c - Why do compilers not warn about out-of-bounds static array indices? - Stack Overflow

Yes, I tried -O3 too. What is the point of having that option if it doesn't do what it says it will?

Perhaps a stupid question:

You are using -O2 and -Warray-bounds at the same time?

35587 � -Warray-bounds does not work at all or does not find all trivial cases, and :works only with -O2 or -O3

See the first post for the man page info. -Warray-bounds is enabled by default with -Wall. Together with -O2 or -O3 or not. It doesn't catch at all. Try and see it for yourself. I am wondering why it is there if it doesn't work..!

Your post#1 suggests you need:

-O2 -Warray-bounds=2

did you read post #6?

Hi hicksd8,
Did you or I miss something?

No, I don't think so. I'm still scratching my head like you and the others.

Some web pages indicate that it works, others say that it doesn't.

You have to be careful with those different web pages. They are not necessarily accurate.