Pointer values changes when using realloc() on pointer to pointer
<p>I have to read from a file which has a unknown number of students records in it written in binary, then sort the students by their GPA and send to stdout.</p>

<p>Our sort function had to be like</p>

<pre><code>void insertion_sort(Student **, int);
</code></pre>

<p>That's why I choose to use an pointer to a pointer to Student (probably not the best solution? I think I could have just sent an pointer to Student like this <code>(&amp;p_to_Student, n)</code> ?)</p>

<p>The code is bellow, the problem is that when I print the first element of what <code>p</code> is pointing to (the first students name) I get gibberish, the other students are fine.</p>

<p>I checked the value of <code>p</code>, and it does change after <code>realloc()</code> is called, and because it's also the address of the first element of <code>p</code> (right?).</p>

<p>Also checked with Valgrind and it returns a bunch of errors about memory leaks!</p>

<p>The code runs fine when there is no <code>realloc()</code> call, also when I initialize <code>p</code> after I'm done reading the file. So it must be something to do with not using <code>realloc()</code> correctly.</p>

<p>Bonus question: is this a proper way to read an unknown number of data entries from a file?</p>

<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

struct student {
    char name[30];
    char surname[30];
    double GPA;
};

typedef struct student Student;

void insertion_sort(Student **arr, int n)
{
    int i,j;

    for (i=1; i&lt;n; i++)
    {
        Student *tmp = arr[i];

        for (j=i; j&gt;0 &amp;&amp; (tmp-&gt;GPA &gt; arr[j-1]-&gt;GPA); j--)
            arr[j] = arr[j-1];

        arr[j] = tmp;
    }
}


int main(int argc, char **argv)
{
    FILE *in;
    Student s, *arr, **p;
    size_t ret;
    int i = 1, n=0, c=2;

    in = fopen(argv[1], "rb"); 
    if (in == NULL)
        return printf("Can't open file!\n"), 1;

    arr = (Student*) malloc(c*sizeof(Student*));
    p = (Student**) malloc(c*sizeof(Student*));

    do
    {
        ret = fread(&amp;s, sizeof(Student), 1, in);

        if (ret)
        {
            if (n == c)
            {
                arr = (Student*) realloc(arr, (c*=2)*sizeof(Student));
                p = (Student**) realloc(p, c*sizeof(Student*));
            }
            // when I print the value of pointer p
            // the values is changed when realloc() is called
            printf("p = %p\n", p);

            arr[n] = s;
            p[n] = arr+n;
            n++;
        }

    } while (ret);

    fclose(in);

    // If I do this instead the program runs correctly        
    //p = (Student**) malloc(c*sizeof(Student));
    //for (int i=0; i&lt;n; i++)
    //{
        //p[i] = arr+i;
    //}

    insertion_sort(p, n);

    for (i=0; i&lt;n; i++)
    {
        printf("%2d. %-20s %-20s %7.2lf\n", i+1, p[i]-&gt;name,
            p[i]-&gt;surname, p[i]-&gt;GPA);
    }

    free(arr);
    free(p);

    return 0;
}
</code></pre>