简体   繁体   中英

arrays using pointers in c++: segmentation fault when accessing the returned array

I'm new to C++ and I'm trying to build a 3 dimensional array using a pointer to a pointer to a pointer. I am sure there are more efficient ways in doing so, but I am trying to understand pointers at the moment.

As example code, I originally had the following piece, which worked fine, allocating, initializing, and releasing the memory.

void builder(int aSize1, int aSize2, int aSize3)
{
    int i1, i2, i3;
    int ***frequencies;

    cout << "allocation started ..." << endl;
    frequencies = new int** [aSize1+1];
    for (i1=0; i1<=aSize1; i1++){
        frequencies[i1] = new int*[aSize2+1];
        for (i2 = 0; i2 <= aSize2; i2++)
        {
            frequencies[i1][i2] = new int [aSize3 + 1];
        }
    }
    cout << "allocation done" << endl;
    cout << " " << endl;

    cout << "before initialization" << endl;
    for (i1=0; i1<=aSize1; i1++){
        for(i2=0; i2<=aSize2; i2++){
            for(i3 = 0; i3 <= aSize3; i3++)
            {
                frequencies[i1][i2][i3]= (i1 * i2) % 10;
            }
        }
    }
    cout << "after initialization" << endl;
    cout << " " << endl;

    /* the "destroyer" part */

    cout << "deleting ..." << endl;

    for (i1=0; i1<=aSize1; i1++){
        for(i2=0; i2<=aSize2; i2++){
            delete [] frequencies[i1][i2];
        }
    }

    for (i1=0; i1<aSize1; i1++){
        delete [] frequencies[i1];
    }
    delete [] frequencies;
    cout << "deleting done" << endl;

}

I wanted to up the ante by splitting the code above into several parts, so that I could use the initialized array in the main() function of my program (just to see if I can access them there as well). So, I ended up doing the following

The header file:

void builder(int aSize1, int aSize2, int aSize3, int*** frequencies)
{
    int i1, i2, i3;
    //int ***frequencies;

    cout << "allocation started ..." << endl;
    frequencies = new int** [aSize1+1];
    for (i1=0; i1<=aSize1; i1++){
        frequencies[i1] = new int*[aSize2+1];
        for (i2 = 0; i2 <= aSize2; i2++)
        {
            frequencies[i1][i2] = new int [aSize3 + 1];
        }
    }
    cout << "allocation done" << endl;
    cout << " " << endl;

    cout << "before initialization" << endl;
    for (i1=0; i1<=aSize1; i1++){
        for(i2=0; i2<=aSize2; i2++){
            for(i3 = 0; i3 <= aSize3; i3++)
            {
                frequencies[i1][i2][i3]= (i1 * i2) % 10;
            }
        }
        cout << **(frequencies[i1]+2) << endl;
    }
    cout << "after initialization" << endl;
    cout << " " << endl;

}

void destroyer( int aSize1, int aSize2, int aSize3, int*** frequencies )
{
    int i1, i2;

    cout << "deleting ..." << endl;

    for (i1=0; i1<=aSize1; i1++){
        for(i2=0; i2<=aSize2; i2++){
            delete [] frequencies[i1][i2];
        }
    }

    for (i1=0; i1<aSize1; i1++){
        delete [] frequencies[i1];
    }
    delete [] frequencies;
    cout << "deleting done" << endl;
}

and my main() where I try to access the 3d array in a fruitless effort.

int main()
{
    int aSize1 = 10;
    int aSize2 = 10;
    int aSize3 = 10;
    int*** freq;

    builder(aSize1, aSize2, aSize3, freq);
    cout << "builder finished" << endl;
    cout << **(freq[1]+2) << endl;
    destroyer( aSize1, aSize2, aSize3, freq);
}

When I compile this, the "builder" function runs fine, but I get a segmentation fault whenever I try to access the 3d array in the main function. I would expect this to work because I have read it in my book that if something is passed by reference using a pointer to a function, the function would have the power to manipulate it. Also, I expected that I would need to dereference the 3d array 3 times (ie ***freq) in order to correctly access the elements, but the compiler gets mad at me for trying to do so and blurts out

myBuilder.cpp:42:17: error: indirection requires pointer operand ('int' invalid) cout << ***(frequencies[i1]+1) << endl;

I know this is a newb question, but any help will be appreciated!

The frequencies pointer in builder and destroyer is a copy of the freq pointer in main . So setting it in builder does not change the (uninitialized) pointer in main . You want a reference to pointer instead:

void builder(int aSize1, int aSize2, int aSize3, int***& frequencies);

And for your levels of indirection, note that if freq is an int*** , then freq[1] is an int** .

In code when you call builder(aSize1, aSize2, aSize3, freq); from main(), you are passing int ***frequencies (that contains garbage value since its inception) and want this triple pointer to be updated within builder function call.

The builder function allocates memory and updates a copy of ***frequecny passed as parameter in builder function call in below code line

frequencies = new int** [aSize1+1];

Thus, it is a call by value for frequency pointer, which is not returned updated in main() after completion of call to builder. It still contains garbage address in it that gets accessed to cause you segmentation fault.

You need to pass the address of frequencies pointer like &frequencies in builder call and make the changes accordingly in builder function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM