0

I know this question was answered but it somehow doesn't work for me. I dynamically allocate memory for array like this:

arr = (int**)(malloc(rows*sizeof(int*)));
arr[0] = (int*)(malloc(rows*columns*sizeof(int))); // <-- THIS DOESN'T WORK

printf("\nArray: \n");
while(fscanf(fp, "%d", &num) == 1) {   
    //arr[row] = (int*)(malloc(columns*sizeof(int))); <---THIS WORKS
    arr[row][col] = num;
    printf("%d ", arr[row][col]);
    if((++col == columns)){
        row++;          
        col = 0;
        printf("\n");
    }
}

It throws segmentation fault after 4th row, if matrix is 6x6. Any advice? Thanks

EDIT: See: http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/ point number 4. If I do it like in point 3, it works. But I need it like in 4.

4
  • What is the question? Commented Oct 5, 2015 at 6:05
  • @juanchopanza If I want array to be allocated in one chunk of memory, I have to allocate it as in line with comment "<-- THIS DOESN'T WORK", problem is.....it doesn't work. If I allocate it in "while", every 1D array would be in different place of memory. Commented Oct 5, 2015 at 6:07
  • And what is the question? Commented Oct 5, 2015 at 6:08
  • Don't cast the result of malloc() in C Commented Oct 5, 2015 at 6:19

4 Answers 4

8

There exists no case where you should use fragmented malloc calls like you do. It is wide-spread but bad and incorrect practice. As you point out, it will not give you a true 2D array in adjacent memory, but rather a fragmented, slow mess.

How to do this properly:

In standard C, write

int (*arr)[rows][columns] = malloc (sizeof(*arr));
(*arr)[r][c] = something;
...

free(arr);

or if you prefer to use syntax which is easier-to-read (but perhaps harder to understand):

int (*arr)[columns] = malloc (sizeof(int[rows][columns]));
arr[r][c] = something;
...

free(arr);

In obsolete versions of C, you will have to write a "mangled array":

int* arr = malloc(rows * columns * sizeof(*arr));
arr[r*c] = something;
...

free(arr);
Sign up to request clarification or add additional context in comments.

2 Comments

Why you call the last one mangled array i do not know. Something else confused me. In the first case sizeof(*arr) equals 4 bytes (or the word size of the computer), does it equal rows * columns * sizeof(int)?
@Nik-Lz It is called "mangled" because you can't use regular 2D array syntax when accessing it, but have to calculate the array index. sizeof(*an_array_pointer) does not equal 4 bytes, but the size of the array. This is a difference between array pointers and regular pointers.
5

To allocate a contiguous memory, you'll have to use

arr  = malloc(sizeof(int *) * rows);
arrayData = malloc(sizeof(int) * columns * rows);

for(i = 0; i < rows; i++)
     arr[i]  = arrayData + i * columns ;

To deallocate you'll need to have

free( arrData );
free( arr );

See here

1 Comment

Search for contiguous memory allocation for 2D array on SO
2

You need to allocate memory for each row, not just the first row. Replace

arr[0] = (int*)(malloc(rows*columns*sizeof(int)));

with

for(int i = 0; i < rows; i++)
    arr[i] = malloc(columns * sizeof(int));

The changes made here are:

  1. All the rows will be allocated columns * sizeof(int) bytes of memory.
  2. Casting the result of malloc is pointless in C. I've removed it.

You might need to add a check in the loop to prevent an overflow. Something like

if(row == rows)
{
    puts("Matrix full; Exiting loop...");
    break;
}

The fixed code would be

int i, row = 0, col = 0;
int rows = 6, columns = 6; /* For 6x6 matrix */

arr = malloc(rows * sizeof(int*));
for(i = 0; i < rows; i++)
    arr[i] = malloc(columns * sizeof(int));

printf("\nArray: \n");
while(fscanf(fp, "%d", &num) == 1) {   
    arr[row][col] = num;
    printf("%d ", arr[row][col]);
    if(++col == columns){
        row++;          
        col = 0;
        printf("\n");
    }
    if(row == rows)
    {
        puts("Matrix full; Exiting loop...");
        break;
    }
}

7 Comments

Your solution is already in my question, see line with comment "<-- THIS WORKS". But if I do it like this, every 1D array of 2D array would be in different place of memory. See: geeksforgeeks.org/dynamically-allocate-2d-array-c point number 4.
You can't do it the way you want to
@iharob Well....ok, everyone seems to think the same, but can you give me a hint why this can't be done?
@Wlad Whoa. That fourth method is really confusing at first glance. Try int i; for(i = 0; i < rows; i++) arr[i] = (arr[0] + i * columns); just after arr[0] = (int*)(malloc(rows*columns*sizeof(int))) in your code.
However, this doesn't allocate a 2D array in adjacent memory cells.
|
2

For a 6x6 matrix, dynamic memory is overkill. You should simply use:

int arr[rows][cols];

This is much simpler, cleaner, quicker, less error prone and generally all round safer — as long as you keep the matrix size small enough that it easily fits on the stack. If you need a large matrix (say from 1 MiB upwards, but you'll need to tune your threshold to suit your systems), then dynamic memory is relevant.

You can make the single allocation to arr[0] work, but you have to do explicit assignments to each of arr[1] through arr[5]. I did it this way:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int rows = 6;
    int cols = 6;
    int **arr = (int**)(malloc(rows*sizeof(int*)));
    arr[0] = (int*)(malloc(rows*cols*sizeof(int)));

    for (int i = 1; i < rows; i++)
        arr[i] = arr[i-1] + cols;

    printf("\nArray: \n");
    for (int i = 0; i < rows; i++)
    {   
        for (int j = 0; j < cols; j++)
            arr[i][j] = (i+1) * (cols + 1 - j);
    }

    for (int i = 0; i < rows; i++)
    {   
        for (int j = 0; j < cols; j++)
            printf("%3d", arr[i][j]);
        putchar('\n');
    }

    free(arr[0]);
    free(arr);
    return(0);
}

Sample output:

Array: 
  7  6  5  4  3  2
 14 12 10  8  6  4
 21 18 15 12  9  6
 28 24 20 16 12  8
 35 30 25 20 15 10
 42 36 30 24 18 12

Running valgrind gives a clean bill of health.

4 Comments

However, this doesn't allocate a 2D array in adjacent memory cells.
The data cells are a single contiguous array.
Oh right... only saw the pointer array allocation and dismissed it. Well anyway, this code is complete obscure, why would you ever want to write something like this? Just allocate an adjacent chunk of memory, no need for the array of pointers.
The OP wanted (or, at least, used) an array of pointers; I fixed up what he said doesn't work (and it didn't work because 83% of the pointers were uninitialized) so it does work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.