abbax il problema che proponi in questo modo è un po' troppo astratto... tra l'altro non hai nemmeno ben specificato dov'è che hai l'errore. Da quello che leggo come commento, l'errore dovrebbe essere qui

codice:
void visualizza(const lista_ptr pila)
{
     printf("\n------------------------");
     printf (" \nNome: %s\n", pila->persona.nome);
		printf(" Cognome: %s\n", pila->persona.cognome);
		printf(" Indirizzo: %s\n", pila->persona.indirizzo);
        printf(" Corso: %s\n", pila->persona.corso);
        printf("------------------------\n");
        visualizza(pila->next); //se inserisco questa istruzione, windows crasha, se non la inserisco, non mi stampa nulla       
}
e mi chiedevo se è l'unico. In ogni caso, questo credo proprio che sia dovuto al fatto che quella che hai scritto è una funzione che ricorre all'infinito perché non c'è alcun caso base. Quello che vorresti fare tu (a quanto ho capito!) è stampare tutta la lista, ma alla funzione gli devi dire che la chiamata ricorsiva la deve fare fintanto che il campo next del nodo n-esimo della lista non è NULL... altrimenti quando dovrebbe fermarsi?

direi di aggiustare così, tanto per cominciare

codice:
void visualizza(const lista_ptr pila)
{
   if ( pila ) {/* se pila non è nullo */
      printf("\n------------------------");
      printf (" \nNome: %s\n", pila->persona.nome);
      printf(" Cognome: %s\n", pila->persona.cognome);
      printf(" Indirizzo: %s\n", pila->persona.indirizzo);
      printf(" Corso: %s\n", pila->persona.corso);
      printf("------------------------\n");
      visualizza(pila->next);
   }
}