3

I'm attempting to create a simple 2D array in C but apparently running into some memory trouble. My setup is simple enough and I can't tell what's wrong. I admit that my understanding of pointers is insufficient, but I still think this should be working. Can anyone see the flaw here?

typedef unsigned int DATUM;
DATUM **series_of_data;
void initialize_data()
{
    *series_of_data = (DATUM *) malloc(1024 * sizeof(DATUM));
}

This causes my program to crash with a bus error when I run it.

Josh Leitzel
  • 15,089
  • 13
  • 59
  • 76
  • 1
    Double pointers are not 2D arrays. It's extremely inefficient and silly to use them as such unless you want to take advantage of the possibility of permuting rows in O(1) rather than O(cols). Simply use a single pointer and address the row and column with multiplication, or use a pointer-to-vla type (but the latter usage is tricky to get right, C99-specific, and probably not worth it). – R.. GitHub STOP HELPING ICE May 05 '11 at 04:03

3 Answers3

6

series_of_data is actually not allocated.

You have various way to allocates a 2D array, either using the array of rows model whcih has bad cache coherency and thus has usually bad performances or to use the Iliffe vector adviced in Numerical recipes in C that consists in allocating one huge h*w memory block and a side pointer array which contains the beginning of your rows (or columns) :

DATUM** alloc_array( int h, int w )
{
  int i;
  DATUM** m = (DATUM**)malloc(h*sizeof(DATUM*));
  m[0] = (DATUM*)malloc(h*w*sizeof(DATUM));
  for(i=1;i<h;i++) m[i] = m[i-1]+w;
  return m;
}

void release_array(DATUM** m)
{
  free( m[0] );
  free( m);
}

int main()
{
  int r,c;
  DATUM** tab;
  int width  = 5;
  int height = 3;
  tab = alloc_array(height, width); /* column first */

  for(r = 0;r<height;++r)
   for(c = 0;c<width;++c)
    tab[r][c] = (1+r+c);

  for(r = 0;r<height;++r)
  {
    for(c = 0;c<width;++c)
    {
      printf("%d\t",tab[r][c]);
    }
    puts("");
  }
  release_array(tab);
}

Data are nicely packed in memory, so cache are happy and you keep the [][] access pattern. As a matter of speed this is in +/-3% speed of the classical DATUM* + polynomial access method.

Joel Falcou
  • 6,247
  • 1
  • 17
  • 34
1

You haven't allocated the series_of_data pointer before you assign to *series_of_data.

For example, if series_of_data is intended to be an array then you would need to write something like this:

series_of_data = malloc(n*sizeof(DATUM*));

where n is the length of the series_of_data array.

Only after you have done this can you assign to *series_of_data.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

series_of_data is an invalid pointer - you don't assign it to anything. When you try to assign to its memory location (*series_of_data = ...), it's putting stuff in a random place, which is likely to not do what you want. You have to point series_of_data somewhere useful, e.g.

series_of_data = (DATUM **)malloc(16 * sizeof(DATUM *))

for an array with 16 slots for DATUM * pointers in it.

Claudiu
  • 224,032
  • 165
  • 485
  • 680