0

I have two identical functions for allocating a contiguous block of memory for a matrix, one being for an int the other for a double. See below:

double** alloc_2d_double(int rows, int cols) {
    double* data = (double*)malloc(rows * cols * sizeof(double));
    double** array = (double**)malloc(rows * sizeof(double));
    int i;
    for (i = 0; i < rows; i++) {
            array[i] = &(data[cols*i]);
    }

    return(array);
}

int** alloc_2d_int(int rows, int cols) {
    int* data = (int*)malloc(rows * cols * sizeof(int));
    int** array = (int**)malloc(rows * sizeof(int));
    int i;
    for (i = 0; i < rows; i++) {
            array[i] = &(data[cols * i]);
    }

    return(array);
}

The double function works just fine but the int function fails with malloc(): memory corruption. Why does the int function fail when the double doesn't?

This code is for an mpi program and the double function sees calls with parameters 25, 25 and 60, 60 and the int function sees calls with parameters 27, 22 and 100, 100.

Any advice would be greatly appreciated!

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
bburnett
  • 13
  • 1
  • 2
    You've got a 64-bit machine, and `sizeof(double) == sizeof(double *)` so you get away with the mistake in the second `malloc()` in the first function, but `sizeof(int) != sizeof(int *)` so you don't get away with the mistake in the second `malloc()` in the second function. (On a 32-bit machine, you'd be wasting space with the second `malloc()` in the first function, allocating twice as much space as needed.) – Jonathan Leffler Apr 04 '18 at 21:35
  • [Do I cast the result of malloc?](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) **No.** – Deduplicator Apr 04 '18 at 21:54

1 Answers1

1

. v----v wrong type.
double** array = (double**)malloc(rows * sizeof(double)); is the wrong size calculation.

It allocates for double and not double *. So if a double size is more or the same as a pointer, this is simply an over-allocation.

With int** array = (int**)malloc(rows * sizeof(int)); this could be under-allocating on a machine with 32-bit int and 64-bit pointers. @Jonathan Leffler

Better to allocate to the size of the de-referenced pointer than the type to avoid this common mistake. Using sizeof *pointer idiom is easier to code right, review and maintain.

// int** array = (int**)malloc(rows * sizeof(int));
//                   v-----------v   size of the de-referenced pointer               
int** array = malloc(sizeof *array * rows);

Minor points:

Casting the return value of malloc() is not needed in C.

Consider that int * int * size_t may int overflow when size_t * int * int does not. Begin the calculation with the widest type. Recall the sizeof operator return type is size_t.

double** alloc_2d_double(int rows, int cols) {
  // double* data = (double*)malloc(rows * cols * sizeof(double));
  double* data = malloc(sizeof *data * rows * cols);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256