-1

I want to stick 2D arrays in a 3D array together, first i defined the 3D array in the following way

int ***grid;
    grid=new int **[number];

then I want to assign the 2D arrays to the 3D construct

for(i=0;i<number;i++)
        grid[i]=rk4tillimpact2dens(...);

with

int** rk4tillimpact2dens(...
...
  static int** grid;
    grid=new int*[600];
    for(i=0;i<600;i++)
        grid[i]=new int[600];
    memset(grid,0x0,sizeof(grid));
...
  return(grid);
}

so far no problem, everything works fine, but when I want to access the 3D array afterwards I get a seg fault. Like that e.g.

printf("%d",grid[1][1][1]);

What is my mistake?

Best, Hannes

Romero Azzalini
  • 184
  • 1
  • 1
  • 12
  • Welcome to Stack Overflow. Your first mistake is failing to provide a [minimal complete example](https://stackoverflow.com/help/mcve). – Beta Nov 17 '17 at 02:43
  • What are you trying to accomplish with the `memset`? It isn't doing what you think it is. – 1201ProgramAlarm Nov 17 '17 at 02:52
  • can't I set the array with 0's through memset? – Romero Azzalini Nov 17 '17 at 02:57
  • @1201ProgramAlarm.: I have explained that in answer. – user2736738 Nov 17 '17 at 02:58
  • @RomeroAzzalini one of the fundamental misunderstanding here is "*a pointer is not an array*" and "*an array is not a pointer*". An array guarantees elements that are sequential in memory. A *pointer to pointer to type* (or in your case a *pointer to pointer to pointer to type*) does not. – David C. Rankin Nov 17 '17 at 04:35
  • @DavidC.Rankin thank you for making that point clear! but in general it should make no difference, as long as you don't program some fancy time optimezed stuff? – Romero Azzalini Nov 17 '17 at 05:39
  • @RomeroAzzalini Oh no -- it does. That's what the answers are saying. While you may be able to assign a pointer to the beginning of a 2D array, (that being `int (*ptr)[cols]`) you cannot take a 2D array and assign a *pointer to pointer to `int`* (e.g. `int **ptp = 2Darray;`). The first is a *pointer to an array of `[cols]` values*, the second is a *pointer to a pointer to `int`*. Think about it this way, after `ptr++;`, where would `ptr` point. After `ptp++;` what does `ptp` point to? – David C. Rankin Nov 17 '17 at 06:35
  • @DavidC.Rankin oh, I see. Yes, it was a bit late :D... Thanks for your help!! – Romero Azzalini Nov 17 '17 at 21:55

5 Answers5

0

Printing out the address

printf("%p",&grid[1][1][1]);

You are printing the address here. That's why you may not get what you desire to see.

printf("%d",grid[1][1][1]);

This will print the array element.

And to read an input from stdin you will use scanf() which requires you to pass address of an variable.

scanf("%d",&grid[1][1][1]);

Zeroing out the allocated memory

Also you can't get the size of the array using sizeof. SO to initialize with 0 you use memset on the chunks that are allocated at once with a new.

In your case example would be Like 1201ProgramAlarm pointed out

for(int i = 0; i < 600; i++){
      ...
      memset(grid[i],0,sizeof(int)*600);
}

There is another way you can initialise an allocated memory in c++.

grid[i]=new int[600]();

For example:

int** rk4tillimpact2dens(...
...
  static int** grid;
    grid=new int*[600];
    for(i=0;i<600;i++)
        grid[i]=new int[600]();

...
  return(grid);
}
user2736738
  • 30,591
  • 5
  • 42
  • 56
0

Oh, sorry, it was typo in my question, I did

printf("%d",grid[1][1][1]);

it's not working :(. But even

printf("%d",&grid[1][1][1]);

or

printf("%d",*grid[1][1][1]);

would not work. The strange thing is, that there are no errors unless I try to access the array

Romero Azzalini
  • 184
  • 1
  • 1
  • 12
  • 1
    [edit](https://stackoverflow.com/posts/47342380/edit) your question instead of writing an answer – kmdreko Nov 17 '17 at 03:23
0

First, you discard the very first row of each matrix with that memset (the actual row is leaked). While technically grid[1][1][1] should still be readable, it probably becomes corrupt in some other place.

Can you provide a minimal verifiable example? This is likely to solve your problem.

bipll
  • 11,747
  • 1
  • 18
  • 32
0

To clear out the memory allocated for grid, you can't do the whole NxN matrix with one memset, it isn't contiguous memory. Since each row is allocated as a separate memory block, you need to clear them individually.

for(i=0;i<600;i++) {
    grid[i]=new int[600];
    memset(grid[i], 0, sizeof(int) * 600);
}

The 600 value should be a named constant, and not a hardcoded number.

And grid does not need to be a static variable.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
0

Do you expect memset(grid,0x0,sizeof(grid)); not to zero the pointer values you've just assigned to grid[0] through to grid[599]? If so, you should test that theory by inspecting the pointer values of grid[0] through to grid[599] before and after that call to memset, to find out what memset does to true (more on that later) arrays.

Your program is dereferencing a null pointer which results directly from that line of code. Typically, a crash can be expected when you attempt to dereference a null pointer, because null pointers don't reference any objects. This explains your observation of a crash, and your observation of the crash disappearing when you comment out that call to memset. You can't expect good things to happen if you try to use the value of something which isn't an object, such as grid[1][... where grid[1] is a pointer consisting entirely of zero bits.

The term 3D array doesn't mean what you think it means, by the way. Arrays in C and C++ are considered to be a single allocation, where-as what your code is producing seems to be multiple allocations, associated in a hierarchical form; you've allocated a tree as opposed to an array, and memset isn't appropriate to zero a tree. Perhaps your experiments could be better guided from this point on by a book regarding algorithms, such as Algorithms in C, parts 1-4 by Robert Sedgewick.

For the meantime, in C, the following will get you a pointer to a 2D array which you can mostly use as though it's a 3D array:

void *make_grid(size_t x, size_t y, size_t z) {
    int (*grid)[y][z] = malloc(x * sizeof *grid);
    /* XXX: use `grid` as though it's a 3D array here.
     * i.e. grid[0][1][2] = 42;
     */
    return grid;
}

Assuming make_grid returns something non-null, you can use a single call to memset to zero the entirety of the array pointed to by that function because there's a single call to malloc matching that a single call to memset... Otherwise, if you want to zero a tree, you'll probably want to call memset n times for n items.

In C++, I don't think you'll find many who discourage the use of std::vector in place of arrays. You might want to at least consider that option, as well as the other options you have (such as trees; it seems like you want to use a tree, which is fine because trees have perfectly appropriate usecases that arrays aren't valid for, and you haven't given us enough context to tell which would be most appropriate for you).

autistic
  • 1
  • 3
  • 35
  • 80