Occorre fare molta attenzione con i thread detached: la loro esecuzione continua anche dopo che la crt invoca i distruttori delle classi, per cui se vuoi thread detached bisogna lavorare con codice C (quasi puro).

Qui hai due problemi: il primo riguarda il lifetime delle variabili, il secondo è una race condition abbastanza banale.

1° Problema (con le righe coinvolte) :
codice:
Server::Run() {
    Socket new_sock;
    ...
    while(!thread_stop)
    {
        serversock.accept(new_sock);
        if (new_sock.is_valid())
        {
            cout<<"Ricevuta connessione\n";
            thread_serventi[n_thread] = move(thread(&Server::serviceRoutine,this,&new_sock));
            n_thread++;
        }
    }
    ...
}
Quando thread_stop == true la funzione esce e tutte le variabili al suo interno distrutte. Questo vale anche per new_sock. Però tu non chiedi ai thread_serventi di fermare la loro esecuzione con la join(). Questi thread continueranno la loro esecuzione anche dopo che sei uscito da Run(), di conseguenza il parametro new_sock che ricevono non è più valido all'interno della funzione service routine. E questo perchè lo passi per indirizzo e non per copia.
In breve l'errore è qui: &new_sock

Il secondo problema è che sia thread_stop sia n_thread non sono atomiche e questo può portare a problemi di sincronizzazione tra Run() e Server::WaiForEtc(). Se il tuo compilatore supporta std::atomic<> (header <atomic> rendi atomiche quelle sue variabili.

Ultima cosa: non è detto che il join() riesca sempre. Se il thread non è joinable o è detached invocare una join() lancia un'eccezione.
La cosa corretta sarebbe fare:
codice:
    for (int i = 0; i<n_thread; i++)
    {
        if (thread_serventi[i].joinable()) thread_serventi[i].join();
    }
    if (mainthread.joinable()) mainthread.join();