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;
}
14 answers
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.
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 demad
emain
para realizar uma limpeza adequada, todos os objetos vão ser destruídos corretamente, incluindoptr
eos
. -
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, incluindoos
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 anoexcept
função no meio da pilha de chamadas. Isto está indicado em §15.5.1 [excepto.terminar]:
Então temos que apanhá-lo! Abre uma excepção e apanha-a na main!
- 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 [...][...]
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 [...]
, 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
).
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]:
Pensa nisso agora, porque Farias tal coisa? Quantos objectos magoaste dolorosamente?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.
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 programastd::at_quick_exit
tratadores, nenhuma outra limpeza é realizada. -
std::exit
provoca uma terminação normal do programa e, em seguida, chamadasstd::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 astd::terminate_handler
que chamastd::abort
por defeito.
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.
Chama o std::exit
função.
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:
- vais acabar por ter vários pontos de saída do programa
- torna o código mais complicado (como usar goto)
- Ele não pode libertar memória alocada no tempo de execução
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.
return 0;
coloque isso onde quiser dentro de int main()
e o programa irá fechar imediatamente.
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.
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
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.
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.
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.
Para quebrar uma condição use o return (0);
Então, no seu caso seria: if(x==1)
{
return 0;
}
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();
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);
*(int*) NULL= 0;
Isto dá-me uma boa coredump de onde posso examinar a situação.