0

I have a 2D array which originally looks like the following qrow are defined earlier in my code. I have an input query.txt file, which essentially count the rows of that text file with a loop, and define

int qrow = result of the loop count

This value is not changed later on in the code. Similarly for attrow. In this specific test case,

qrow = 10
attrow = 19

Usage Matrix:

int usage [qrow][attrow];
// Assigned values using a while loop

Usage matrix
0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0

0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0

0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0

0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0

1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0

1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1

0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0

0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0

0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0

Then I created another array as following:

int aq [qrow][attrow];

I assigned value to aq matrix with another while loop, however I notice if I print out my usage matrix again, values were changed. In specific I found the following example

cout<<"Before, usage[0][7] = "<<usage[0][7]<<endl;
aq[10][9] = 20;
cout<<"After, usage[0][7] = "<<usage[0][7]<<endl;

Output:

Before, usage[0][7] = 1
After, usage[0][7] = 20

Can anyone explain why is this behaving this way? Also appreciate potential resolution to this problem. Thanks!

FYI, below is the actual while loop which is causing this issue,

while(a<qrow){
    while(b<attrow){
    // Compute A(att=a, q = b)
    // initialise aq entry to zero
    aq[b][a] = 0;

    int use = usage[b][a];
    if (use == 0){
        aq[a][b] = 0;
        b=b+1;
        continue;
    }
    int sum = 0;
    int k = 0;
    while ( k< freqcol){
            double temp = freqMat[b][k];
            sum = sum + temp;
            k=k+1;
        }
        aq[b][a] = sum;
        b=b+1;
    }
a=a+1;
b=0;

}

Usage matrix after loop,

Usage matrix
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 -2147483648 -2147483648

-2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0

0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0
13
  • 6
    Please edit your question to include a proper minimal reproducible example. What is qrow? What is attrow? How are they defined? How are they initialized? Commented Aug 30, 2021 at 8:36
  • 3
    My crystal ball says you're accessing outside the bounds of one of the arrays and happen to stomp on the other. Commented Aug 30, 2021 at 8:37
  • 2
    int aq [qrow][attrow]; -- If qrow and attrow are not const, then this is not valid C++. Arrays in C++ must have their size denoted by a constant expression, not a runtime computed value. Commented Aug 30, 2021 at 8:39
  • 4
    Also, you define int aq [qrow][attrow]; and use the loops while(a<qrow) and while(b<attrow). But then you also use aq[b][a] = 0 which will work if and only if qrow == attrow. Otherwise you will go out of bounds and have undefined behavior. Commented Aug 30, 2021 at 8:41
  • 2
    If the values of the dimensions can change at run-time then use std::vector instead. Commented Aug 30, 2021 at 9:03

1 Answer 1

1

Without being to able to tell exactly what's going on, you're most likely going out of bounds with your array indices.

If both arrays are on the stack, their memory regions will be adjacent:

Array 1:                              Array 2:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Now if you go out of bounds with your array indices, you're likely to write to the memory of the other array. For example, if you do array2[-1] = 20, you will write to the last element of the first array:

Array 1:                              Array 2:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                          array2[-1]^ ^array2[0]

Likewise, you will write to array 2 if you're using too large indices to access array 1:

Array 1:                              Array 2:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          array1[length_of_array1-1]^ ^array1[length_of_array1]

Needless to say: DON'T do this on purpose. This just serves to explain what you're observing and doing this is undefined behavior, i.e. you cannot rely on this to happen.

Possible solution: Use STL containers like std::array or std::vector and use iterators or a range-based for loop to safely iterate over the elements, like so:

#include <array>

std::array<int, 10> array1;
// Fill array somehow
...

for (auto& i : array1) {   // reference here, because we want to write to the element
   // do something
}

With nested std::vectors, in case you need runtime values for the size:

#include <vector>

size_t rows, columns;
...

std::vector<std::vector<int>> array1{};

// here we resize the vectors to have the desired number of elements
array1.resize(rows);
for (auto& row : array1) {
   row.resize(columns);
}

for (auto& row : array1) {
   for (auto& element : row) {
      // do something
   }
}

If you absolutely have to use indices, make sure you're not going out of bounds.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for the answer, I will test out with your suggested method.
Using std::array<int, 10> array1; What is the correct syntax if I want to define a 2D array?
That would be std::array<std::array<int, M>, N>>, M and N being the respective array dimensions.
@WayneTan Be aware, though, that with this approach you are exploring the field of undefined behaviour and such a programme is not valid according to the standard. It's pretty likely that you can observe described behaviour, but there's no guarantee for...
@WayneTan Note that with 2D std::array you need to invert the dimensions you actually want to use, i.e. to get the equivalent to int[row][column] you need to write std::array<int, column>, row>. That's due to how templates work and that's actually where I regret standard committee having defined template <typename T, size_t S>class array {...} instead of template <size_t S, typename T>class array {...}.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.