Como terminar o código C++

gostaria que o meu código C++ parasse de correr se uma determinada condição for cumprida, mas não sei como fazer isso. Então, a qualquer momento, se uma declaração if for verdadeira, termine o código assim:

if (x==1)
{
    kill code;
}
 218
c++
Author: Peter Mortensen, 2015-05-15

14 answers

Há várias maneiras, mas primeiro tens de perceber porque é que a limpeza de objectos é importante, e daí a razão.std::exit é marginalizado entre os programadores de c++.

RAII e Desembrulhamento da pilha

C++ faz uso de um idioma chamado RAII, O que em termos simples significa que os objetos devem realizar a inicialização no construtor e limpeza no destruidor. Por exemplo:std::ofstream classe [maio] abrir o arquivo durante o construtor, em seguida, o usuário executa operações de saída nele, e finalmente no final de seu ciclo de vida, geralmente determinado por seu escopo, o destruidor é chamado que essencialmente fecha o arquivo e descarrega qualquer conteúdo escrito no disco.

O que acontece se não chegar ao destruidor para puxar o autoclismo e fechar o ficheiro? Quem sabe?Mas talvez não escreva todos os dados que devia escrever no ficheiro.

Por exemplo, considere este código

#include <fstream>
#include <exception>
#include <memory>

void inner_mad()
{
    throw std::exception();
}

void mad()
{
    std::unique_ptr<int> ptr(new int);
    inner_mad();
}

int main()
{
    std::ofstream os("file.txt");
    os << "Content!!!";

    int possibility = /* either 1, 2, 3 or 4 */;

    if(possibility == 1)
        return 0;
    else if(possibility == 2)
        throw std::exception();
    else if(possibility == 3)
        mad();
    else if(possibility == 4)
        exit(0);
}
O que acontece em cada um a possibilidade é:
  • Possibilidade 1: retorno essencialmente deixa o escopo da função atual, então ele sabe sobre o fim do ciclo de vida de {[[4]} assim chamando o seu destruidor e fazendo a limpeza adequada, fechando e limpando o arquivo para o disco.
  • possibilidade 2: abrir uma excepção também cuida do ciclo de vida dos objectos no âmbito actual, fazendo assim uma limpeza adequada...
  • Possibilidade 3: acção! Mesmo que a exceção seja lançada em inner_mad, o unwinder irá embora a pilha de mad e main para realizar uma limpeza adequada, todos os objetos vão ser destruídos corretamente, incluindo ptr e os.
  • Possibilidade 4: bem, aqui? exit é uma função C e não é consciente nem compatível com os idiomas c++. It não realiza limpeza nos seus objectos, incluindo os no mesmo âmbito. Para que o seu ficheiro não seja fechado correctamente e por esta razão, o conteúdo pode nunca ser escrito nele!
  • outras possibilidades: ele vai deixar o escopo principal, realizando um implícito {[[12]} e, portanto, ter o mesmo efeito que a possibilidade 1, ou seja, uma limpeza adequada.

Mas não tenha tanta certeza sobre o que eu acabei de lhe dizer (principalmente possibilidades 2 e 3); continue lendo e vamos descobrir como realizar uma limpeza adequada baseada em exceção.

Possíveis Formas De Terminar

Regressar de main!

Você deve fazer isso sempre que possível; sempre prefere retornar do seu programa, retornando um status de saída adequado do main.

A pessoa que ligou do seu programa, e possivelmente o sistema operacional, pode querer saber se o que o seu programa era suposto fazer foi feito com sucesso ou não. Por esta mesma razão você deve retornar ou zero ou EXIT_SUCCESS para sinalizar que o programa terminou com sucesso e EXIT_FAILURE para sinalizar o programa terminado sem sucesso, qualquer outra forma de valor de retorno é definida pela implementação (§18.5/8).

No entanto, você pode estar muito fundo na pilha de chamadas, e devolver tudo isso pode ser doloroso...

[não] abrir uma excepção

Abrir uma excepção irá realizar uma limpeza adequada de objectos usando a remoção da pilha, chamando o destruidor de todos os objectos em qualquer âmbito anterior. Mas aqui está a captura! É a implementação-definido se a limpeza de chaminés é realizada quando uma excepção não é manuseada (pela captura (...) clause) or even if you have a noexcept função no meio da pilha de chamadas. Isto está indicado em §15.5.1 [excepto.terminar]:
  1. Em algumas situações, o tratamento de excepções deve ser abandonado por técnicas menos subtis de tratamento de erros. [Nota: estas situações são:

    [...]

    - quando o mecanismo de tratamento de exceções não é possível encontrar um manipulador para uma exceção lançada (15.3), ou quando a busca por um manipulador (15.3) encontra o bloco Mais externo de uma função com uma noexcept-Especificação que não permite a exceção (15.4), ou [...]

    [...]

  2. Em tais casos, std:: terminate () é chamado (18.8.3). Na situação em que não é encontrado nenhum manipulador correspondente, é definido pela implementação se a pilha está ou não desligada antes da DST:: terminate () é chamada [...]

Então temos que apanhá-lo! Abre uma excepção e apanha-a na main!

, uma vez que não identificada exceções não podem realizar desenrolar a pilha (e, consequentemente, não executar a limpeza adequada), devemos capturar a exceção principal e, em seguida, retornar a um estado de saída (EXIT_SUCCESS ou EXIT_FAILURE).

Então, uma boa configuração seria:
int main()
{
    /* ... */
    try
    {
        // Insert code that will return by throwing a exception.
    }
    catch(const std::exception&)  // Consider using a custom exception type for intentional
    {                             // throws. A good idea might be a `return_exception`.
        return EXIT_FAILURE;
    }
    /* ... */
}

[Não] DST::exit

Isto não execute qualquer tipo de pilha de descompressão, e nenhum objeto vivo na pilha irá chamar o seu respectivo destruidor para realizar a limpeza.

Isto é imposto em §3.6.1/4 [básico.Comece.init]:

Terminar o programa sem sair do bloco atual (por exemplo, chamando a função std:: exit (int) (18.5)) não destrói nenhum objeto com duração de armazenamento automático (12.4) . Se std:: exit é chamado para terminar um programa durante a destruição de um objeto com duração estática ou de armazenamento de thread, o programa tem um comportamento indefinido.

Pensa nisso agora, porque Farias tal coisa? Quantos objectos magoaste dolorosamente?

Outras [más] alternativas

Existem outras maneiras de terminar um programa (além de bater) , mas não são recomendadas. Só para esclarecer, vão ser apresentadas aqui. Notice how normal program termination não significa desenrolamento da pilha, mas um estado para o sistema operativo.
  • std::_Exit causa uma interrupção normal do programa, e é isso.
  • std::quick_exit provoca uma terminação e chamadas normais do programa std::at_quick_exit tratadores, nenhuma outra limpeza é realizada.
  • std::exit provoca uma terminação normal do programa e, em seguida, chamadas std::atexit manipuladores. Outros tipos de limpeza são realizados, tais como chamar objetos estáticos destruidor.
  • std::abort provoca uma terminação anormal do programa, nenhuma limpeza é realizada. Isto deve ser chamado se o programa terminou de uma forma realmente, realmente inesperada. Não fará mais do que sinalizar ao SO sobre a terminação anormal. Alguns sistemas realizam uma descarga de núcleo neste caso.
  • std::terminate chama a std::terminate_handler que chama std::abort por defeito.
 383
Author: Denilson Amorim, 2015-05-16 16:37:30
Como Martin York mencionou, a saída não faz a limpeza necessária como o regresso faz. É sempre melhor usar o regresso no local de saída. No caso de você não estar no principal, onde quer que você gostaria de sair do programa, volte para o principal em primeiro lugar.

Considere o exemplo abaixo. Com o seguinte programa, um arquivo será criado com o conteúdo mencionado. Mas se o return for comentado e não recomendado exit (0), o compilador não lhe garante que o ficheiro terá o necessário texto.

int main()
{
    ofstream os("out.txt");
    os << "Hello, Can you see me!\n";
    return(0);
    //exit(0);
}

Não é só isto, ter vários pontos de saída num programa tornará a depuração mais difícil. Use a saída apenas quando puder ser justificada.

 55
Author: Narendra N, 2015-05-16 15:20:44

Chama o std::exit função.   

 40
Author: Otávio Décio, 2013-06-07 14:59:13

As pessoas estão a dizer "saída de chamada(código de retorno)", mas isto é uma má forma. Em programas pequenos é bom, mas há uma série de problemas com isso:

  1. vais acabar por ter vários pontos de saída do programa
  2. torna o código mais complicado (como usar goto)
  3. Ele não pode libertar memória alocada no tempo de execução
A única altura em que deves sair do problema é com esta linha principal.cpp:
return 0;

Se estiver a usar o exit() para manipular erros, você deve aprender sobre exceções (e nidificação exceções), como um método muito mais elegante e seguro.

 23
Author: jkeys, 2009-07-14 07:04:01

return 0; coloque isso onde quiser dentro de int main() e o programa irá fechar imediatamente.

 14
Author: Evan Carslake, 2015-05-15 03:40:22

Devolve um valor da sua main ou usa a função exit. Ambos têm um int. Não importa que valor você retorna, a menos que você tenha um processo externo observando o valor de retorno.

 12
Author: Goz, 2010-02-17 12:48:40

O programa terminará quando o fluxo de execução chegar ao fim da função principal.

Para terminar antes disso, você pode usar a função exit (int status), onde o status é um valor retornado para qualquer que tenha iniciado o programa. 0 indica normalmente um estado sem erro

 11
Author: chrisbunney, 2009-07-12 17:44:04

Se você tem um erro em algum lugar profundo no código, então pode abrir uma exceção ou definir o código de erro. É sempre melhor abrir uma excepção em vez de definir códigos de erro.

 10
Author: Jagannath, 2015-05-18 08:30:00

Geralmente usaria o método exit() com um estado de saída apropriado .

Zero significaria uma corrida bem sucedida. Um status não-zero indica que algum tipo de problema ocorreu. Este código de saída é usado pelos processos-mãe (por exemplo scripts shell) para determinar se um processo foi executado com sucesso.

 9
Author: Brian Agnew, 2015-05-28 09:27:50
Para além da chamada de saída(error_code) - que chama os tratadores atexit, mas não os destruidores RAII, etc. - cada vez mais uso excepções.

Cada vez mais o meu programa principal parece

int main(int argc, char** argv) 
{
    try {
        exit( secondary_main(argc, argv );
    }
    catch(...) {
        // optionally, print something like "unexpected or unknown exception caught by main"
        exit(1);
    }
}

Em que o secondary_main onde todas as coisas que foram originalmente foram colocadas -- isto é, a principal original é renomeada secondary_main, e o stub principal acima é adicionado. Este é apenas um nicety, de modo que não há muito Código entre a bandeja e catch no principal.

Se quiseres, apanha. outros tipos de excepções.
Eu gosto muito de pegar tipos de erro de cadeia, como std:: string ou char*, e imprimir esses no encarregado das capturas na main. Usando exceções como esta, ao menos permite que destruidores RAII sejam chamados, para que eles possam fazer a limpeza. O que pode ser agradável e útil.

Em geral, o tratamento de erros em C-saída e sinais - e o tratamento de erros em C++ - tentativa/captura/lançamento de excepções-brincam de forma inconsistente, na melhor das hipóteses.

Então, onde você detecta um erro

throw "error message"

Ou algum tipo de excepção mais específico.

 7
Author: Krazy Glew, 2013-03-01 23:18:05

Para quebrar uma condição use o return (0);

Então, no seu caso seria:
    if(x==1)
    {
        return 0;
    }
 0
Author: Lavender, 2017-03-15 12:49:23

Se a sua declaração if estiver em ciclo, pode utilizar

 break; 

Se quiser escapar a algum código e continuar a repetir Use:

Continuar;

Se a sua declaração if não estiver em ciclo pode utilizar:

 return 0;

Or 




  exit();
 -1
Author: Akshay, 2017-01-17 11:31:39
Meu... exit() a função é definida em stdlib.h Tens de adicionar um pré-processador.

Colocar include stdlib.h na secção de cabeçalho

Então use exit(); onde quiser, mas lembre-se de colocar um número interger no parêntesis de saída.

Por exemplo:

exit(0);
 -2
Author: rdxxdroid, 2016-03-10 20:26:46
Se a condição para a qual estou a testar é má notícia, faço isto:
*(int*) NULL= 0;
Isto dá-me uma boa coredump de onde posso examinar a situação.
 -2
Author: dodo, 2016-07-12 20:01:20