abort indica o fim "anormal" do programa e aumenta o sinal POSIX SIGABRT, o que significa que qualquer manipulador que você registrou para aquele sinal será invocado, embora o programa ainda termine após as palavras em ambos os casos. Normalmente, você usaria abortem um programa C para sair de um caso de erro inesperado em que o erro provavelmente fosse um bug no programa, em vez de algo como uma entrada incorreta ou uma falha de rede. Por exemplo, você pode abortse uma estrutura de dados tiver um ponteiro NULL, quando isso logicamente nunca deveria acontecer.
exit indica um final "normal" para o programa, embora isso ainda possa indicar uma falha (mas não um bug). Em outras palavras, você pode exitreceber um código de erro se o usuário fornecer uma entrada que não pode ser analisada ou um arquivo não pode ser lido. Um código de saída 0 indica sucesso. exittambém opcionalmente chama manipuladores antes de terminar o programa. Eles são registrados com as funções atexite on_exit.
std :: terminate é o que é chamado automaticamente em um programa C ++ quando há uma exceção não tratada. Isso é essencialmente o C ++ equivalente a abort, supondo que você esteja relatando todos os seus erros excepcionais por meio de exceções lançadas. Isso chama um manipulador que é definido pela std::set_terminatefunção, que por padrão simplesmente chama abort.
Em C ++, você geralmente deseja evitar a chamada abortou exitcom erro, já que é melhor lançar uma exceção e deixar o código mais acima na pilha de chamadas decidir se é ou não apropriado encerrar o programa. Se você usar ou não exitpara o sucesso é uma questão de circunstância - se faz ou não sentido terminar o programa em algum lugar diferente da instrução de retorno em main.
std::terminatedeve ser considerada uma ferramenta de relatório de erros de última hora, mesmo em C ++. O problema std::terminateé que o manipulador de terminação não tem acesso à exceção que não foi tratada, portanto, não há como saber o que era. Normalmente, é muito melhor envolver todo o main em um try { } catch (std::exception& ex) { }bloco. Então, pelo menos, você pode relatar mais informações sobre exceções derivadas de std::exception(embora, é claro, as exceções que não derivam de std::exceptionainda não sejam tratadas).
Encapsular o corpo de mainem try { } catch(...) { }não é muito melhor do que definir um manipulador de terminação, porque novamente você não tem acesso à exceção em questão. Edit: De acordo com a resposta de Neil Butterworth, há um benefício em que a pilha é desfeita neste caso, o que (um tanto surpreendentemente) não é verdadeiro para uma exceção não tratada.