3

I have a function designed to malloc an array and then fill it with values from a file (n-dimensional coordinates, although working in 2d for now).

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

#define dim 2

typedef struct {
    double **array; /*store the coordinates*/
    int num; /* store the number of coordinates*/
    /* store some other things too */
} foo;

void read_particles(foo *bar);

int main(void)
{
    foo bar;

    read_particles(&bar);

    printf("\n");
    for(int i = 0; i < bar.num; i++)
        printf("%f %f\n", bar.array[0][i], bar.array[1][i]);

    /* printf here does not output the array properly.
     * Some values are correct, some are not.
     * Specifically, the first column bar.array[0][i] is correct, 
     * the second column bar.array[1][i] is not, some values from the 
     * first column are appearing in the second.
     */


    return 0;
}

void read_particles(foo *bar)
{
    FILE *f = fopen("xy.dat", "r");

    /* read number of coordinates from file first*/
    fscanf(f, "%d", &bar->num);

    bar->array = (double**) malloc(bar->num * sizeof(double*));
    for(int i = 0; i < bar->num; i++)
        bar->array[i] = (double*) malloc(dim * sizeof(double));

    for(int i = 0; i < bar->num; i++)
    {   
        for(int j = 0; j < dim; j++)
            fscanf(f, "%lf", &(bar->array[j][i]));

        /* For now, coordinates are just 2d, print them out
         * The values are displayed correctly when printing here*/
        printf("%f %f\n", bar->array[0][i], bar->array[1][i]);
    }

    fclose(f);
}

Some sample data is available here.

When the values are printed from inside the function they are fine, when printed outside the function they are not. So I must not be dealing with the pointers properly. It may (or may not) be worth noting that I originally was not using a struct and had the function defined as double **read_and_malloc(num), returning the pointer to the array, and the output produced was identical.

So what is going on?

I can include some sample data, or any other information if need be.

Sam
  • 222
  • 2
  • 12
  • Is `dim` same as `bar->num`? – R Sahu Mar 02 '15 at 23:04
  • Dim is the number of dimensions of each coordinate, bar.num is the number of coordinates, so in the end I should have array[dim][num]. – Sam Mar 02 '15 at 23:06
  • So, in other words.. *maybe* ??? You did this: `malloc(bar->num * sizeof(double*))`, the follow-up `for` loop had better be using a value no larger than `bar->num`, whatever that is, as the corresponding top-limit, or your code will step into undefined behavior. – WhozCraig Mar 02 '15 at 23:07
  • Sorry, that was a transcription error, the loop should run to `bar->num`. To clarify, i have `num` coordinates in `dim` dimensions. (Fixed in the question). – Sam Mar 02 '15 at 23:12
  • Thank you Matt, I had not seen that page, I'll prepare a complete working example. – Sam Mar 02 '15 at 23:15
  • 1
    Ok, the code that is there now compiles and reproduces the problem. – Sam Mar 02 '15 at 23:48

2 Answers2

3

Your second loop is not correct:

for(int i = 0; i < dim; i++)
    bar->array[i] = (double*) malloc(dim * sizeof(double));

You create bar->num elements yet you iterate over dim elements:

bar->array = (double**) malloc(bar->num * sizeof(double*))

The loop should iterate over the number of elements in the first dimension: bar->num

reader
  • 496
  • 2
  • 15
2

In the updated code you are allocating bar->num rows and 2 columns. However, your fscanf and printf code tries to work on array with 2 rows and bar->num columns.

To keep your reading/writing code intact, the allocation code would be:

bar->array = malloc(dim * sizeof *bar->array);
for (int i = 0; i < dim; ++i)
    bar->array[j] = malloc(bar->num * sizeof *bar->array[j]);

NB. If you're not familiar with this malloc idiom, see here

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • This seems to have fixed the problem, I'll test it thoroughly in the morning to be sure. Thank you. – Sam Mar 03 '15 at 00:34