Scrivendo

codice:
typedef char* string;
string str;
non stai allocando niente, stai solo dichiarando un puntatore a carattere (a voler essere pignoli, stai allocando staticamente spazio per un puntatore a carattere). Se vuoi ricorrere all'allocazione dinamica devi utilizzare le funzioni apposite (malloc() e calloc()), oppure ricorri all'allocazione statica riscrivendo la typedef, ad esempio, come ti ho mostrato sopra. Dichiarare semplicemente un puntatore non comporta l'allocazione di spazio in memoria (che poi di quanto dovrebbe essere se non lo specifichi?).

Il fatto che il programma ti crashi sulla fclose() è casuale (ti ripeto, il tuo programma sulla mia macchina, col mio sistema e col mio compilatore crasha immediatamente dopo la fscanf()), se proprio vuoi sapere cosa succede nello specifico armati di un debugger serio e mettiti ad analizzare la situazione dei registri del processore man mano che il tuo programma viene eseguito. Si chiama buffer overflow.