I'm building a code to simulate the response of some dynamical systems for my PhD. Basically what I'm trying to do is:
- Ask the user for the name of a input file that contains all parameters for the simulation;
- Read the input file and assign each parameter to a specific variable in my program.
- Do the calculations.
I'm having problems on step 2, as one of the values in the input file is the dimension dim
of an dinamically allocated array *x
.
Here is a working example of the code:
#include <stdio.h>
#include <stdlib.h>
void read_file(char *name, int *dim, double **x) {
// Open input file
FILE *input = fopen(name, "r");
if (input == NULL) {
// Return error
perror(name);
return;
}
// Read and assign system constants
fscanf(input, "%i", dim);
printf("dim = %i\n", *dim);
// Allocate memory for x[dim]
*x = malloc((*dim) * sizeof(*x));
double y[(*dim)];
printf("size of (*x) = %llu\n", sizeof(*x));
printf("size of y = %llu\n", sizeof(y));
// Security check for pointers
if(*x == NULL) {
free(*x);
printf("Memory allocation for *x did not complete successfully\n");
return;
}
// assign values to x[dim] vector
for (int i = 0; i < *dim; i ) {
fscanf(input, "%lf", &(*x)[i]);
printf("(*x)[%i] = %lf\n", i, (*x)[i]);
}
// Close input file
fclose(input);
}
char *get_input_filename(void) {
char *filename = malloc(200 * sizeof(*filename));
printf("Enter Input Filename: ");
scanf("%s", filename);
return filename;
}
int main (void) {
int DIM;
double *x = NULL;
char *input_filename = get_input_filename();
read_file(input_filename, &DIM, &x);
printf("size of (*x) = %llu\n", sizeof(*x));
for (int i = 0; i < DIM; i ) {
printf("(*x)[%i] = %lf\n", i, x[i]);
}
free(x); free(input_filename);
}
And here is the content of the input file in.txt
for this example:
5
0.0 0.1 0.2 1.4 2.6
When I call *x = malloc((*dim) * sizeof(*x));
I expected to find the dimension of the system to be 5 * 8bytes
, as the value for *dim
is assigned in the previous line, however only 8 bytes
are allocated. Then, I declared the y[(*dim)]
variable to check if the sizeof
a VLA
would behave in the same way as the sizeof
*x
, just to compare. The sizeof(y)
was what I expected, but the sizeof(*x)
wasn't, as shown in the output:
Enter Input Filename: in.txt
dim = 5
size of (*x) = 8
size of y = 40
(*x)[0] = 0.000000
(*x)[1] = 0.100000
(*x)[2] = 0.200000
(*x)[3] = 1.400000
(*x)[4] = 2.600000
size of (*x) = 8
(*x)[0] = 0.000000
(*x)[1] = 0.100000
(*x)[2] = 0.200000
(*x)[3] = 1.400000
(*x)[4] = 2.600000
I understand that it cannot allocate memory if the value of *dim
is unknown, but a value is assigned in the previous line.
Also, I even don't know how the program assigned values to (*x)
successfully as it don't have the necessary allocation of bytes to do it.
What am I missing here? How can I allocate the memory correctly?
Thanks in advance
CodePudding user response:
Both dim
and x
are output arguments; pointers that refer to locations where you're to store your results of this function (a size and a memory allocation sequence of double
values).
This is where things are going off the rails:
*x = malloc((*dim) * sizeof(*x));
The left side is ok. And so is most of the right side. But if you're ever allocating to a pointer based on the size of the dereferenced data a pointer points to, you need to do so using just that: the size of the thing the pointer points to. x
is a pointer-to-pointer, *x
is a pointer, and the latter is the 'thing' we're allocating memory for, the address of which will be stored at *x
.
Therefore, that should be:
*x = malloc((*dim) * sizeof **x);
Note: when I'm using variables as the operator argument for sizeof
I personally strive not to use parens. It ensures I'm actually using a variable id rather than a type id, since the latter isn't allowed without parens. use what you favor at your discretion/whim.
More fundamental, however, your familiarity and understanding of sizeof
is wrong and/or misled. You cannot acquire the size of dynamic-allocated memory region using sizeof
. Using the sizeof
operator on a pointer variable will give you exactly what you asked for: the size of the pointer variable (e.g. the size of a pointer). It is your responsibility to maintain and track magnitude of dynamic allocations (which, btw, your code does, using dim
).