如何结束c++代码

我想我的c++代码停止运行,如果某个条件得到满足,但我不知道如何做到这一点。因此,在任何时候,如果if语句为真,就像这样终止代码:

if (x==1)
{
kill code;
}
452756 次浏览

调用std::exit函数。,,

要么返回main的值,要么使用exit函数。两者都采用int型。返回什么值并不重要,除非有一个外部进程监视返回值。

通常你会使用exit()方法和一个合适的退出状态

零意味着成功运行。非零状态表示发生了某种问题。父进程(例如shell脚本)使用此退出码来确定进程是否成功运行。

当执行流到达主函数的末尾时,程序将终止。

要在此之前终止它,可以使用exit(int status)函数,其中status是返回到启动程序的值。0通常表示非错误状态

正如Martin York提到的,退出不像返回那样执行必要的清理。

在exit的位置使用return总是更好。

.

.

.

.

. 考虑下面的例子。 使用下面的程序,将用所提到的内容创建一个文件。 但是如果return被注释&无注释退出(0),编译器不保证文件将有所需的文本
int main()
{
ofstream os("out.txt");
os << "Hello, Can you see me!\n";
return(0);
//exit(0);
}
不仅如此,在程序中有多个退出点会使调试更加困难。

.

.

.

如果在代码深处的某个地方出现错误,那么要么抛出异常,要么设置错误代码。抛出异常总是比设置错误代码更好。

人们常说“调用退出(返回代码)”,但这是不好的形式。在小程序中是可以的,但是有一些问题:

  1. 您最终将从程序中获得多个退出点
  2. 它使代码更加复杂(比如使用goto)
  3. 它不能释放在运行时分配的内存

实际上,你唯一应该退出这个问题的时候是main.cpp中的这一行:

return 0;

如果您正在使用exit()来处理错误,那么您应该了解异常(以及嵌套异常),这是一种更加优雅和安全的方法。

Beyond calling exit(error_code) -调用退出处理程序,但不调用RAII析构函数等。 -我越来越多地使用异常

我的主程序越来越像

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);
}
}
< p > secondary_main的地方 所有原本放东西的地方 例如,原来的main被重命名为secondary_main,上面的存根main被添加。 这只是一个细节,这样main中的tray和catch之间就不会有太多代码

如果你想,捕获其他异常类型 我很喜欢捕捉字符串错误类型,比如std::string或char*,然后打印出来

使用这样的异常至少允许调用RAII析构函数,这样它们就可以进行清理。这可能是愉快和有用的。

总的来说,C错误处理-退出和信号-和c++错误处理-尝试/捕获/抛出异常-在最好的情况下不一致地一起发挥作用。

然后,检测到错误

throw "error message"

或者一些更特定的异常类型。

有几种方法,但首先你需要理解为什么对象清理是重要的,以及std::exit在c++程序员中被边缘化的原因。

RAII和Stack Unwinding

c++使用了一个名为RAII的习语,简单来说,这意味着对象应该在构造函数中执行初始化,在析构函数中执行清理。例如,std::ofstream类[可以]在构造函数期间打开文件,然后用户对其执行输出操作,最后在其生命周期的末尾(通常由其作用域决定)调用析构函数,这实际上是关闭文件并将任何写入的内容刷新到磁盘。

如果没有使用析构函数刷新并关闭文件,会发生什么?谁知道!但它可能不会写入所有的数据,它应该写入文件。

例如,考虑下面的代码

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


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


void mad()
{
auto ptr = std::make_unique<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);
}

每种可能性发生的情况是:

  • 可能性1: Return实际上留下了当前函数的作用域,因此它知道os的生命周期结束,从而调用它的析构函数,并通过关闭文件并将文件刷新到磁盘来进行适当的清理。
  • 可能性2:抛出异常还会处理当前范围内对象的生命周期,从而进行适当的清理…
  • 这里堆栈展开进入行动!即使在inner_mad抛出异常,展开器将遍历madmain的堆栈以执行适当的清理,所有对象都将被正确地销毁,包括ptros
  • 嗯,这里?exit是一个C函数,它不知道也不兼容c++习惯用法。它对你的对象执行清理,包括同样作用域的os。因此,您的文件将无法正确关闭,因此,内容可能永远不会写入其中!
  • 它将只留下main作用域,通过执行隐式return 0,从而具有与可能性1相同的效果,即适当的清理。

但不要太确定我刚刚告诉你的(主要是可能性2和3);继续阅读,我们将了解如何执行适当的基于异常的清理。

结束的可能方法

从主舱回来!

只要有可能,你就应该这样做;总是倾向于通过从main中返回适当的退出状态来从程序返回。

程序的调用者(可能还有操作系统)可能想知道程序应该做的事情是否成功完成。出于同样的原因,你应该返回0或EXIT_SUCCESS来表示程序成功终止,返回EXIT_FAILURE来表示程序不成功终止,任何其他形式的返回值都是由实现定义的(§18.5/8)。

然而,你可能在调用堆栈中非常深,返回所有的可能是痛苦的…

[不]抛出异常

抛出异常将通过调用任何先前作用域中每个对象的析构函数,使用堆栈展开执行适当的对象清理。

但是这里是问题!当抛出的异常未被处理(通过catch(…)从句)时,是否执行堆栈展开,甚至在调用堆栈中间有noexcept函数时,都是由实现定义的。这在§15.5.1 [except.terminate]中声明:

  1. 在某些情况下,必须放弃异常处理,采用不那么微妙的错误处理技术。[注:这些情况是:

[…]

- 当异常处理机制无法为抛出的异常找到处理程序时(15.3),或者当搜索处理程序时(15.3)遇到具有noexcept-specification的函数的最外层块时不允许异常(15.4),或[…]

[…]

  1. 在这种情况下,std::terminate()被调用(18.8.3)。在没有找到匹配的处理程序的情况下,在调用std::terminate()之前是否展开堆栈是由实现定义的[…]

所以我们必须抓住它!

请抛出异常并在main捕获它!

由于未捕获的异常可能不会执行堆栈展开(因此不会执行适当的清理),因此我们应该在main中捕获异常,然后返回退出状态(EXIT_SUCCESSEXIT_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;
}
/* ... */
}

[不要]std::exit

这不会执行任何类型的堆栈展开,堆栈上的活动对象也不会调用其各自的析构函数来执行清理。

这在§3.6.1/4 [basic.start.init]中强制执行:

在不离开当前块的情况下终止程序(例如,调用std::exit(int)函数(18.5))不会破坏任何具有自动存储持续时间的对象(12.4)。如果std::exit被调用来结束一个程序,在一个对象的静态或线程存储持续时间的销毁过程中,该程序具有未定义的行为。

现在想想,你为什么要做这样的事?你痛苦地损坏过多少物品?

其他(糟糕的)选择

还有其他方法可以终止程序(撞车除外),但不推荐使用。为了澄清起见,它们将在这里呈现。注意正常程序终止 表示堆栈展开,而操作系统的状态是好吧

  • std::_Exit导致正常的程序终止,仅此而已。
  • std::quick_exit导致正常的程序终止并调用std::at_quick_exit处理程序,不执行其他清理操作。
  • std::exit导致一个正常的程序终止,然后调用std::atexit处理程序。执行其他类型的清理,例如调用静态对象析构函数。
  • std::abort导致程序异常终止,不执行清除操作。如果程序以一种非常非常意想不到的方式终止,应该调用这个函数。它只会向操作系统发出异常终止的信号。在这种情况下,一些系统执行核心转储。
  • std::terminate调用默认调用std::abortstd::terminate_handler

return 0;将它放在int main()中的任何你想要的地方,程序将立即关闭。

伙计……exit()函数定义在stdlib.h下

所以你需要添加一个预处理器。

include stdlib.h放在头部分

然后在任何你喜欢的地方使用exit();,但记得在exit的括号中放入一个整数。

例如:

exit(0);

如果我正在测试的情况确实是坏消息,我会这样做:

*(int*) NULL= 0;

这给了我一个很好的coredump,从那里我可以检查情况。

如果你的If语句在循环中,你可以使用

 break;

如果你想转义一些代码&使用方法:

继续;

如果你的If语句不在循环中,你可以使用:

 return 0;


Or








exit();

打破一个条件使用return(0);

所以,在你的情况下,它将是:

    if(x==1)
{
return 0;
}