Would you class this as a bug;

Ok, so this was my bad as I did a rookie off by one error, but this should not have happened anyway; what do you think?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

class myClass {

		int myInts[2];
		int other;
		
	public:
		myClass() {

			other = 42;
			myInts[0] = 1;
			myInts[1] = 2;
			myInts[2] = 0;

			std::cout << "Other = " << other << std::endl;
	
		}
};
int main() {

	myClass();
	return(0);
	
}


On some compilers you will get a warning, but on others it will just build without any warning at all (my main build machine being the perfect example), but the point is that when you run this code it will print the value of "other" as 0 rather than 42. Now I know exactly why it happens, but surely it shouldn't.

PS. In ordinary procedural code the value of the integer "other" is retained and the program below prints 42 as one would expect.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main() {

	int myInts[2];
	int other;
	other = 42;
	myInts[0] = 1;
	myInts[1] = 2;
	myInts[2] = 0;
	std::cout << "Other = " << other << std::endl;
	return(0);
	
}
Last edited on
 
myInts[2] = 0


This is undefined behaviour. You are creating an array of 2 values, but you're writing to the "third" element which does not exist.

What you're doing, basically, is writing to memory chunks which do not belong to you

Probably, you're writing 0 to the variable other's reserved memory

In fact, if you try to change that bad assignment to something else

myInts[2] = 999;

You could end up with Other = 999

You're going out of bounds with that assignment.

Last edited on
Now I know exactly why it happens, but surely it shouldn't.

Why shouldn't it? Your program's behavior is undefined. The consequences of this are simple:
This International Standard imposes no requirements upon the behavior of programs which contain undefined behavior.
http://eel.is/c++draft/intro.execution#4

Your compiler can emit whatever code it wants.
Last edited on
This was discovered while using ncurses forms library that according to the documentation requires the FIELD** array to be terminated with a null pointer. I did the MAX_ENUMs trick and then made the mistake of using MAX_ENUMs for the terminator.

Like I said Ged, I know why it is doing it and exactly what I have done wrong, but I am still a bit annoyed that the compiler didn't catch my mistake. It catches most things and this is such an easy mistake to make (and such a nightmare to debug when you replace the int's with pointers to external library objects) that I am surprised it wasn't caught.

We all make mistakes when we are writing programs and thankfully the compiler picks up on most of them (undefined behaviour included). I just do not think that a compiler should build a program where something is defined outside of the boundaries of the array that it is supposed to be assigned to. It just doesn't make sense.



You can tell your compiler to treat warnings as errors with -Werror
If you want safety, use a vector instead of a plain array. And use the at() function which does range checking for you.

http://www.cplusplus.com/reference/vector/vector/at/
Note: this is a run-time check, it isn't caught during compilation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>

int main()
{
   
	std::vector<int> myInts(2);
	int other;
	other = 42;
	myInts.at(0) = 1;
	myInts.at(1) = 2;
	myInts.at(2) = 0;
	std::cout << "Other = " << other << std::endl;
	
}

Output:
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.


Notice the message: "contact the application's support team" - that means you - or whoever was responsible for writing the code.

std::array<> supports bounds checked access http://en.cppreference.com/w/cpp/container/array/at
I just do not think that a compiler should build a program where something is defined outside of the boundaries of the array that it is supposed to be assigned to. It just doesn't make sense.

This would slow the compiler way down if you added nannyware for all the possible bug conditions in c++ like common pointer fubars (which is what an array index out of bounds really is). Instead, c++ gave us nannyware objects that prevent these problems, and you can choose which to use. If you want to use a C array or pointer instead of a vector, you need to get it right :)


Fair comment Chervll but in this instance that isn't an option because in the actual production code I am loading up an array from a C library (ncurses FIELD**).

In the production code I had FIELD** declared followed by FORM* which, when you run gdb will make it appear as though it is something wrong with the forms library.

When I wrote a little test program after failing to spot my error, I could not reproduce it (as I just wrote a quick procedural program). For a while it looked like there was some issue with declaring FIELD** in a class and the long and short of it is that it has been a total nightmare to debug (especially with my older compiler not even producing a warning).

The way the forms library works is that you declare each field and then terminate the array with a nullptr. What I was doing wrong was assigning MAX_FORM_FIELDS = '\0' which would have been fine if I had declared my field array as MAX_FORM_FIELDS + 1 or the preferred option which is to put a TERMINATOR element before MAX_FORM_FIELDS in my enumeration list.

@Ged, -Werror will not work on the box I am coding for because it does not show as a warning (even with -Wall) on g++ 4.8.2 (which is what I am stuck with on AIX for now);

To be honest I am just venting because of the amount of time that it has taken to debug this as there is nothing I can do about it only learn from my mistakes :/

C++ puts all the responsibility in the developer's hands.
He doesn't care if you go out of bounds or mess the memory up.

It gives you freedom, which is the price to pay for getting the best of the performance from your machines.

It might not be newbie-friendly... but a Standard Library is provided (STL) for both newbies and professionals, which is well developed and keeps you from making most of the common mistakes.

Smart pointers are an example of what STL provides in order to avoid messing up with pointers.

> it does not show as a warning (even with -Wall) on g++ 4.8.2

With -O2 or above, it should show up as a warning with -Wall

-Warray-bounds
This option is only active when -ftree-vrp is active (default for -O2 and above). It warns about subscripts to arrays that are always out of bounds. This warning is enabled by -Wall.
https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Warning-Options.html#Warning-Options


https://wandbox.org/permlink/vz0dPxRWXOfzzZuz
@JLBorges: Thanks for that, as it has narrowed down the problem quite significantly.

g++ Test.cpp -Wextra -O2 -std=c++11 -pedantic-errors

Builds without any sort of warning on AIX so it looks like this is a bug exclusive to the AIX version of the compiler.

To be fair, there is like one guy who builds rpm's that will install on AIX (http://www.perzl.org/aix/) and he has to do all manner of workarounds to get it to compile in the first place so. He also tries to maintain compatibility with the AIX toolbox for linux. Actually I have just looked at the latest version of the toolbox and they have compiled 6.3 do I will update and see what happens.

IBM have their own proprietary compiler (XLC) that they charge the earth for so we don't use that.

The great thing about building stuff natively on AIX is that if it will run on it then it will run on anything.
> g++ Test.cpp -Wextra -O2 -std=c++11 -pedantic-errors
> Builds without any sort of warning on AIX

Try adding either -Warray-bounds or better, -Wall which includes -Warray-bounds
You are a star! -Wall doesn't make a difference on its own but

g++ TestNoPointer.cpp -o TestNoPointer.app -Wextra -O2 -std=c++11 -pedantic-errors -Wall

did the trick.

Thanks!
Topic archived. No new replies allowed.