程序终止

参考:Program Termination

c++程序终止方式共有3

  1. 调用exit
  2. 调用abort
  3. main函数调用return表达式

exit

参考:

exit Function

exit

声明在头文件stdlib.h,其参数值作为程序返回代码或退出代码。按照惯例,返回0表示成功退出

void exit (int status);

stdlib.h中定义了两个返回代码常量:

/* We define these the same for all machines.
   Changes from this to the outside world should be done in `_exit'.  */
#define EXIT_FAILURE    1   /* Failing exit status.  */
#define EXIT_SUCCESS    0   /* Successful exit status.  */

main函数使用return语句等同于使用返回值作为参数调用exit函数

abort

参考:

abort Function

abort

声明在头文件stdlib.h,函数abort表示终止C++程序

void abort() noexcept;

其和exit函数的区别在于

  • exit函数允许运行时终止进程(run-time termination processing)发生(将会调用全局对象析构函数)
  • abort函数立即终止程序

return

参考:return Statement in Program Termination (C++)

功能上和exit函数相同

退出注意事项

参考:

Using exit or return

  • 构造:全局对象(global object)在main函数执行前进行构造
  • 退出:在执行exit或者return语句后,按相反顺序执行析构函数

如果执行abort函数,就不会调用对象的析构函数

示例代码

#include <iostream>
#include <cstring>
#include <array>

using std::cout;
using std::endl;

class ShowData {
public:
    // Constructor opens a file.
    ShowData(const char *szDev) {
        filename = szDev;
        cout << "construct: " << filename << endl;

        OutputDev = fopen(szDev, "w");
    }

    // Destructor closes the file.
    ~ShowData() {
        cout << "destruct: " << filename << endl;
        fclose(OutputDev);
    }

    // Disp function shows a string on the output device.
    void Disp(char *szData) {
        fputs(szData, OutputDev);
    }

private:
    FILE *OutputDev;
    const char *filename;
};

ShowData sd3 = "sd3";

ShowData sd4 = "sd4";

int main() {
    cout << "begin" << endl;

    ShowData sd1 = "sd1";

    ShowData sd2 = "sd2";

    sd1.Disp("hello to default device\n");
    sd2.Disp("hello to file hello.dat\n");
    sd3.Disp("hello to sd3");
    sd4.Disp("hello to sd4");

    cout << "end" << endl;

//    abort();
    return 0;
}

注意:上面代码中全局对象的定义顺序

结果

construct: sd3
construct: sd4
begin
construct: sd1
construct: sd2
end
destruct: sd2
destruct: sd1
destruct: sd4
destruct: sd3

atexit

参考:

Using atexit

atexit

在调用全局对象的析构函数之前会调用atexit函数

如果对程序指定了多个atexit函数,则它们都将以栈的形式按相反顺序执行(即最后一次调用将第一个执行)

示例如下:

...
...
void f() {
    cout << "quickly, exit will happen" << endl;
}

int main() {
    cout << "begin" << endl;

    ShowData sd1 = "sd1";

    ShowData sd2 = "sd2";

    sd1.Disp("hello to default device\n");
    sd2.Disp("hello to file hello.dat\n");
    sd3.Disp("hello to sd3");
    sd4.Disp("hello to sd4");

    cout << "end" << endl;

    atexit(f);

    return 0;
}

结果

construct: sd3
construct: sd4
begin
construct: sd1
construct: sd2
end
destruct: sd2
destruct: sd1
quickly, exit will happen
destruct: sd4
destruct: sd3

abort

参考:Using abort

调用abort函数中止程序不仅会绕过局部和全局对象的析构函数,还会绕过atexit函数的调用,示例如下:

...
    atexit(f);

    abort();

    return 0;
}

结果:

construct: sd3
construct: sd4
begin
construct: sd1
construct: sd2
end

只有构造函数,没有析构函数了