I have a 2D jagged array declared in my main()
block. This is to be passed to a function to have memory allocated to it. The following is the most reduced case which compiles but crashes when it runs. Where am I going wrong?
#include <stdio.h>
#include <stdlib.h>
void alloc2d(double ***p);
int main () {
double **data;
alloc2d(&data);
printf("Before assign to data\n");
data[0][0] = 0.1;
printf("After assign to data\n");
free(data);
}
void alloc2d(double ***p) {
int i, n, m;
// Get some dynamically assigned sizes
printf("Enter size: ");
scanf("%d %d", &n, &m);
// Now allocate
*p = malloc(n * sizeof(double*));
for (i = 0; i < n; i++) {
*p[i] = malloc(m * sizeof(double));
}
printf("End of alloc2d\n");
}
This reads the values but crashes when I enter low numbers (ie '1 1') but crashes when I enter high numbers (ie '10 10').
You made a very simple syntax error
*p[i] = (double*)malloc(m * sizeof(double));
should really be
(*p)[i] = (double*)malloc(m * sizeof(double));
This is because in C, [] operator has higher precedence than *. So when you type *p[i]
, it is translated into **(p + i)
.
This means: you are asking the compiler to calculate the address by offsetting the address of p by i * sizeof(double**)
, which is clearly not what you actually want.
So, in order to force the compiler to dereference p first, simply surroud *p
with brackets.
Operator precedence is the answer. *p[i]
is equivalent to *(p[i])
. This makes you access memory that lies right after the data
pointer, which will either corrupt some other variables on the stack, or crash completely.
You were looking for (*p)[i]
, which will be the i-th entry in the newly allocated array.
What your alloc2d() allocates is not really a 2D array, but:
Multi-dimensional arrays in C are only possible, if all but the last of the dimensions are known at compile-time:
double a[5][11];
Maybe, this program can help you understand... Note, how COLUMNS is a compile-time constant, even if rows is a run-time variable:
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <err.h>
typedef double myrow_t[11]; /* 11 columns */
#define COLUMNS (sizeof(myrow_t)/sizeof(double))
static unsigned
alloc2d(myrow_t **pd)
{
unsigned int rows;
printf("Enter the number of rows: ");
while (scanf("%u", &rows) != 1)
printf("\ninvalid input, please, try again: ");
*pd = malloc(rows * sizeof(**pd));
if (*pd == NULL)
err(EX_TEMPFAIL, "Out of memory");
return rows;
}
int
main()
{
myrow_t *d;
unsigned int row, column, rows;
rows = alloc2d(&d);
for (row = 0; row < rows; row++)
for (column = 0; column < COLUMNS; column++)
d[row][column] = row * column;
for (row = 0; row < rows; row++) {
printf("Row %3d:\t", row);
for (column = 0; column < COLUMNS; column++)
printf("%.0f\t", d[row][column]);
puts("");
}
free(d);
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.