0

In the following code, when run using GNU GCC v8.2.0, code does not terminate:

int main(void)
{
    /* code */
    int myArray[] = {2, 4};
    int otherArray[] = {777, 888};

    for(int i = 0; i<4; i++)
    {
        myArray[i] = 0;
        cout << "myArray[" << i << "]=";
        cout << myArray[i] << endl;
        cout << "add: " << &myArray[i] << endl;
    }

    for(int i = 0; i<2; i++)
    {
        cout << "otherArray[" << i << "]=";
        cout << otherArray[i] << endl;
        cout << "add: " << &otherArray[i] << endl;
    }



    return 0;
}

output:

add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]=0
add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]=0
add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]=0
add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]^C
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • 2
    Your program has [undefined behavior](https://stackoverflow.com/a/4105123/7478597). `int myArray[] = {2, 4};` defines an `int[2]` but a few lines later you write elements with index 0 ... 3 (here: `for(int i = 0; i<4; i++) { myArray[i] = 0;` – Scheff's Cat Sep 05 '19 at 05:38
  • 1
    You might be corrupting the stack when writing to `myArray[2]` and `myArray[3]` – SHG Sep 05 '19 at 05:39
  • @SHG is there any way to stop corruption of stack from these kinds of code. Also is this a defined behaviour? – Vishal gupta Sep 05 '19 at 05:47
  • Please, have a look at this: [SO: Accessing an array out of bounds gives no error, why?](https://stackoverflow.com/q/1239938/7478597). This may help to understand your issue... – Scheff's Cat Sep 05 '19 at 05:51
  • 1
    If you write array elements which you didn't allocate before (i.e. accessing elements behind end of array) you may write into memory of other variables or things which are stored there. This might be e.g. the storage of your index variable `i` in `for` loop. However, that's fully beyond your control. That's why the term undefined behavior is used (instead of e.g. a crash). The latter might happen - one possible behavior but it's simply not predictable. Instead, the consequence could be completely harmless and non-observable. It's just... undefined behavior. – Scheff's Cat Sep 05 '19 at 05:56
  • I suggest using std::vector instead of C arrays – nada Sep 05 '19 at 06:40

2 Answers2

2
for(int i = 0; i<4; i++)

Replace the 4 in the 'for loop' by 2 like this:

for(int i = 0; i<2; i++)

Since you're using a static array so it's better to specify the fixed size, but the most important is to be aware when you try to access the array by comparing the index being processed with the size of the array to avoid this behavior.

XBlueCode
  • 785
  • 3
  • 18
  • Yeah. Or `myArray` should be declared/defined with sufficient size. ;-) – Scheff's Cat Sep 05 '19 at 05:39
  • Since you're using a static array so it's better to specify the fixed size, but the most important is to be aware when you try to access the array by comparing the index being processed with the size of the array to avoid this behavior. – XBlueCode Sep 05 '19 at 05:47
  • @AbdelfettahBesbes even though I am accessing out off bound for myArray, shouldn't it stop by printing garbage values after 4 iterations? – Vishal gupta Sep 05 '19 at 05:50
  • @Scheff, Thanks) – XBlueCode Sep 05 '19 at 05:55
  • 1
    @Vishalgupta, This is an undefined behavior which means the result is unpredictable during execution and it can be even different in every execution. – XBlueCode Sep 05 '19 at 06:00
  • @Vishalgupta you are writing to memory, not just reading it. If you would be just reading, then it would most likely just output garbage or crash on invalid access, but because you write into memory, you will most likely overwrite some value which is important for other parts of code, causing completely weird behaviour. In this case the infinite loop is quite nice, with complex apps and large source similar bug often keeps silent until much later some completely different part of code starts to "act werid", these bugs are then difficult to find. (using valgrind and static analysis tools helps) – Ped7g Sep 05 '19 at 10:29
1

You are invoking undefined behaviour by writing the indexes 0-3 of the 2 element array myArray.

As this is undefined behaviour there are no guarantees as to what is happening or what will happen if you run the code again in the future. A likely explanation for your observed behaviour is that when you write myArray[2] that is actually overwriting the value of i causing your loop to restart back at 0.

The simple solution is to make myArray larger or change your for loop limit to 2.

To detect this sort of behaviour use std::array instead and call the at function which has bounds checking and will throw an exception when you go outside the bounds of the array. e.g.:

#include <array>
#include <iostream>

int main(void)
{
    /* code */
    std::array< int, 2 > myArray = { 2, 4 };
    std::array< int, 2 > otherArray = { 777, 888 };

    for(int i = 0; i<4; i++)
    {
        myArray.at(i) = 0;
        std::cout << "myArray[" << i << "]=";
        std::cout << myArray[i] << "\n";
        std::cout << "add: " << &myArray.at(i) << "\n";
    }

    for(int i = 0; i<2; i++)
    {
        std::cout << "otherArray[" << i << "]=";
        std::cout << otherArray.at(i) << "\n";
        std::cout << "add: " << &otherArray.at(i) <<  "\n";
    }

    return 0;
}

std::array also has the bonus of a size() method which can make your code safer too:

    for(int i = 0; i<myArray.size(); i++)
    {
        myArray.at(i) = 0;
        std::cout << "myArray[" << i << "]=";
        std::cout << myArray[i] << "\n";
        std::cout << "add: " << &myArray.at(i) << "\n";
    }
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60