0

So, I recently tried doing this:

void Foo(int **bar, int size) {
    bar = new int *[size];
    for (int i = 0; i < size; i++)
        bar[i] = new int[4];
    // Do other stuff
    return;
}

int main(int argc, char *argv[]) {
    int ** data;
    int size = atoi(argv[1]);
    Foo(data, size);
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < 4; j++)
            cout << "i = " << i << ", j = " << j << ", data = " << data[i][j] << endl;
        // Do other stuff
    }

    for (int i = 0; i < size; i++)
        delete[] data[i];
    delete[] data;
    return 0;
}

and invariably I would get a segfault right at that cout statement. After changing the code so that the array was dynamically allocated in main the problem went away. So, the difference between a segfault is whether or not an array is dynamically allocated and destroyed in the same function. This seems wrong to me as this shouldn't be a problem with traditional C++. I am using a MacBook with Xcode for the g++ command. Can anyone else confirm that Xcode's implementation does this?

Paul R
  • 208,748
  • 37
  • 389
  • 560
Woody1193
  • 7,252
  • 5
  • 40
  • 90
  • 1
    Your code invokes undefined behavior due to pointer mismanagement. There is nothing wrong with your C++ compiler or installation. – PaulMcKenzie Nov 15 '15 at 06:28
  • 1
    If you had inspected the value of `data` after the call to `Foo`, you should have seen that `data` didn't change at all. That's what all the answers given to you will explain. Also: http://stackoverflow.com/questions/27487495/c-pointers-and-pointer-to-a-reference/27487983#27487983 – PaulMcKenzie Nov 15 '15 at 06:35
  • @PaulMcKenzie I did inspect `data` after I called `Foo` and I did notice that it hadn't changed. However, I was under the impression that sending any pointer to a function was a pass-by-reference. And the answer given below does explain my problem, thank you – Woody1193 Nov 15 '15 at 15:58
  • 1
    A better example is if you set data to NULL before you called `Foo`. You would have seen that `data` would still be NULL, thus your `cout` would be working with a NULL pointer (undefined behavior). And no, sending a pointer is pass-by-value, no different than any other value type being passed. Pass-by-reference in C++ means *exactly* that -- passing a reference. A pointer is not a reference. – PaulMcKenzie Nov 15 '15 at 18:10

2 Answers2

1

It's nothing specific to Xcode or g++ - just a bug in your code - you need to pass bar by reference in order to use it as an output parameter.

Change:

void Foo(int **bar, int size)

to:

void Foo(int ** &bar, int size)

Note that in general it's preferable to use e.g. std::vector rather than naked C-style pointers for arrays etc.

Paul R
  • 208,748
  • 37
  • 389
  • 560
0

You pass data to Foo by value, so data in main () remains uninitialized when you allocate memory inside Foo.

Eugene
  • 6,194
  • 1
  • 20
  • 31