Home > OS >  How to allocate memory equal in size to a variable read from an input file?
How to allocate memory equal in size to a variable read from an input file?

Time:06-04

I'm building a code to simulate the response of some dynamical systems for my PhD. Basically what I'm trying to do is:

  1. Ask the user for the name of a input file that contains all parameters for the simulation;
  2. Read the input file and assign each parameter to a specific variable in my program.
  3. 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).

  • Related