Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I seeing different behavior between arrays allocated on the heap and the stack?

I am inspecting the behavior of two 2D arrays in C++, one allocated from the stack, and one allocated from the heap.

I create two, 2D arrays of the same shape, and populate those arrays with some data. Then I attempt to read the arrays in two different methods, the first being with the simple array index format "Arr[ROW][COLUMN]". Then I read the arrays using a pointer dereference, and I get two different results for the heap allocated array, but identical results for the stack allocated array. I am trying to understand why the results differ. I would appreciate any clarification that someone can provide. Thanks in advance.

The code I am running is below:

#include <iostream>

using namespace std;

int main(){

    int rows = 6;
    int columns = 3;

    // allocate from the stack.
    double q[rows][columns];

    // allocate from the heap.
    double ** a;
    a = new double*[rows];

    for(int i = 0; i < rows; ++i){
        a[i] = new double[columns];
    }

    // populate the arrays.
    for(int i = 0; i < rows; ++i){
        for(int j = 0; j < columns; ++j){
            a[i][j] = columns*i+j;
            q[i][j] = columns*i+j;
        }
    }

    cout << "*****************" << endl;
    cout << "Array indexing method." << endl;
    cout << "*****************" << endl;

    // print the heap allocated array using array indexing.
    for(int i = 0; i < rows; ++i){
        for(int j = 0; j < columns; ++j){
            cout << a[i][j] << '\t';
        }
        cout << endl;
    }

    cout << "*****************" << endl;

    // print the stack allocated array using array indexing.
    for(int i = 0; i < rows; ++i){
        for(int j = 0; j < columns; ++j){
            cout << q[i][j] << '\t';
        }
        cout << endl;
    }

    cout << "*****************" << endl;
    cout << "Pointer dereferencing method." << endl;
    cout << "*****************" << endl;

    // print the heap allocated array.
    for(int i = 0; i < rows; ++i){
        for(int j = 0; j < columns; ++j){
            cout << *(&a[0][0] + columns*i + j) << '\t';
        }
        cout << endl;
    }

    cout << "*****************" << endl;

    // print the stack allocated array.
    for(int i = 0; i < rows; ++i){
        for(int j = 0; j < columns; ++j){
            cout << *(&q[0][0] + columns*i + j) << '\t';
        }
        cout << endl;
    }
    cout << "*****************" << endl;

    // release the memory allocated to the heap.
    for(int i = 0; i < rows; ++i){
        delete[] a[i];
    }

    delete a;

    return 0;
}

And the results I obtain are:

*****************
Array indexing method.
*****************
0       1       2
3       4       5
6       7       8
9       10      11
12      13      14
15      16      17
*****************
0       1       2
3       4       5
6       7       8
9       10      11
12      13      14
15      16      17
*****************
Pointer dereferencing method.
*****************
0       1       2
0       3       4
5       0       6
7       8       0
9       10      11
0       12      13
*****************
0       1       2
3       4       5
6       7       8
9       10      11
12      13      14
15      16      17
*****************

And I can see that in the third block of output, the heap allocated array isn't being read properly, but the stack allocated array is.

Thanks again.

like image 379
Josh M. Avatar asked Dec 03 '22 21:12

Josh M.


1 Answers

&q[0][0] gives you a pointer to the first double in a block containing rowsxcolumns doubles. While &a[0][0] gives you a pointer the first double in a block containing columns doubles (you've allocated it using a[0] = new double[columns];, remember?). So accessing it columns*i + j will be out of bounds and will triggers Undefined Behavior.

like image 122
user7860670 Avatar answered May 16 '23 07:05

user7860670