codice:
node* elimina(node* n, int val)
{
    if (val == n->valore)
        return elimina(n->next->next, val);
    else
        return elimina(n->next, val);
}

Se però avessi un elemento soltanto, esempio 1.
Inserissi come elemento da eliminare 1.

nel primo if, val e n->valore sarebbero uguali.

quindi si attiverebbe la funzione
return elimina(n->next->next, val);

n->next->next punta a una zona di memoria non esistente, e il programma va in crash(almeno così mi ha fatto più volte).
Questo perchè n->next sarebbe il NULL, ma n->next->next non esiste (o meglio, e una zona di memoria dove non si sa che ci sia), e possono accadere cose strane.
Quindi penso che questo mi manda in crash quando provo a usare questa funz. .




------------
Quello che ho usato su:
Con la prima funzione elimino i successivi elementi partendo dal primo , fin quando non raggiungo NULL, oppure se il primo elemento è diverso da quello che cerco si ferma.
In questo modo l punterà sempre l'elemento in testa (e non perdo nulla durante la stampa).
Successivamente faccio partire l'altra funzione che si occuperà di controllare gli elementi (sapendo che il primo è diverso da val).

Se mi capitasse la situazione che mi manda in crash con il tuo algoritmo:
In pratica faccio partire la prima, vede che c'è il valore 1, e lo elimina e punta a NULL.
A questo punto il ciclo termina, perchè l==NULL.
Parte la seconda funzione e vede che il primo elemento è NULL, quindi termina anche questa.

Se avessi 1-2-2-1 , e volessi eliminare 2, la prima controllerebbe se il valore è in testa, non essendoci, partirebbe la seconda, che cancellerebbe tutti gli elementi a partire dal successivo.
Ed l punterebbe sempre in testa.
Usandone solo una, spesso mi ritrovavo pezzi scollegati, se usavo diverse combinazioni di valori.
Così sono sicuro che il primo elemento punterà sempre a qualcosa (essendo diverso da val), e quando stamperò l, l partirà dall'elemento in testa.


Cioè questo per dire che l'ho provata, ma non sembra andare, anche se sono sicuro che esista qualche algoritmo più compresso, ma in grado di controllare tutti i casi, molto simile a quello che dici.

Cioè la prima versione che mi hai postato, funzionava, ma mi eliminava soltanto il primo elemento trovato, e gli altri li lasciava.
La seconda mi da il problema che può in alcuni casi puntare una zona di memoria che non appartiene alla lista di elementi.


Ho trovato anche un'altro caso, se ho 35-1-1-2 e devo togliere 35 che è l'ultimo elemento della coda.
Ho dovuto cambiare il codice di eliminacentro, aggiungendo l'else (se non si trova in mezzo ma alla fine).

codice:
nodo* lista::eliminacentro(nodo* l, int val)  //elimina elementi dopo il primo
{
    if(l!=NULL && l->succ!=NULL)
    if (val == l->succ->valore){
    l->succ=l->succ->succ;
    return eliminacentro(l, val);
    }
    else
        return eliminacentro(l->succ, val);;
    };