进程终止
参考博客
进程正常终止
进程正常终止的方法有3种:
exit()与_exit()函数
exit()和_exit()的效果都是让程序退出执行,而_exit()用来“尽快”退出
extern void exit (int __status) __THROW __attribute__ ((__noreturn__));
extern void _exit (int __status) __attribute__ ((__noreturn__));
区别:
- _exit直接进入内核,exit则先执行一些清除处理(在进程退出之前要检查文件状态,将文件缓冲区中的内容写回文件)再进入内核
- 调用_exit函数时,其会关闭进程所有的,清理内存以及其他一些内核清理函数,但不会刷新流(stdin,stdout,stderr…),exit函数是在_exit函数之上的一个封装,其会调用_exit,并在调用之前会刷新流
- exit()函数在退出前要检查文件的打开情况,把文件缓冲区的内容写回文件,_exit()函数直接将进程关闭,缓冲区的数据将会丢失
Linux标准函数中,“缓冲I/O”的操作,其特征即对应每一个打开的文件,在内存中都有一片缓冲区。每次读文件时,会连续读出若干条记录,在下次读文件时就可以直接从内存的缓冲区读取;同样每次写文件的时候也仅仅是写入内存的缓冲区,等满足了一定的条件(如达到了一定数量或遇到特定字符等),再将缓冲区中的内容一次性写入文件。这种技术大大增加了文件读写的速度
exit()与return
通常在main()之后就没什么待办的事情了,也不会关心exit()和return的差别,但对于C++程序而言,main()中对象的析构函数是在return之后执行的,如果中途调了exit()就不会执行到析构函数
一般情况下,析构函数就是释放对象的资源,而进程退出后,进程所有资源就都被释放了,所以实际上调用exit()退出程序也并不会出现资源泄漏。只是说如果析构函数涉及到与其他进程通信或IO操作等影响到系统其他资源的情况下就要注意了
示例:
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
void exit_func(void)
{
cout << "oh yeah!" << endl;
}
class Date
{
public:
Date(int year1 = 1970, int month1 = 12, int day1 = 31)
{
cout << "Date constructor" << endl;
this->year = year1;
this->month = month1;
this->day = day1;
}
void printDate()
{
cout << year << ":" << month << ":" << day << endl;
}
int isLeapYear() { return 1; }
void setDate(int year, int month, int day) {}
~Date() { cout << "Date destructor!" << endl; }
private:
int year;
int month;
int day;
};
class A
{
private:
int dataA;
public:
A() { cout << "A's constructor" << endl; }
~A() { cout << "A's destructor!" << endl; }
};
class B
{
private:
int dataB;
A dataClassA;
public:
B() { cout << "B's constructor" << endl; }
~B() { cout << "B's destructor!" << endl; }
};
static Date d199;
int main(int argc, char *argv[])
{
cout << "main start" << endl;
Date d1(2022, 6, 14);
d1.printDate();
static Date d2;
A a1;
B b1;
atexit(exit_func);
cout << "main done" << endl;
return 0;
}
运行输出:
prejudice@prejudice-VirtualBox:~/Cplus_learning/bin$ ./wait_return
Date constructor
main start
Date constructor
2022:6:14
Date constructor
A's constructor
A's constructor
B's constructor
main done
B's destructor!
A's destructor!
A's destructor!
Date destructor!
oh yeah!
Date destructor!
Date destructor!
将main()中return 0改为exit(0),运行输出:
prejudice@prejudice-VirtualBox:~/Cplus_learning/bin$ ./wait_return
Date constructor
main start
Date constructor
2022:6:14
Date constructor
A's constructor
A's constructor
B's constructor
main done
oh yeah!
Date destructor!
Date destructor!
看到main()中定义的对象的析构没有被调用
进程异常终止
进程异常终止主要有两种方式:
- 进程
接受到特定的信号。这个信号可以是进程自己产生的,也可以是来自其他进程或内核。例如,进程企图访问越界的内存地址或者是除数为0时,内核都会产生信号中断进程 调用abort。这其实是第1种情形的特例,因为它产生一个SIGABRT信号
#include <stdlib>
extern void abort (void) __THROW __attribute__ ((__noreturn__));
abort()函数与exit()、_exit()函数区别:
- abort()函数异常终止进程,进程的文件描述符未关闭,占用资源未释放
- exit()、_exit()正常终止进程,关闭进程的文件描述符并释放资源
示例:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
float x, y;
while (1)
{
cout << "Input the value of x: ";
cin >> x;
cout << "Input the value of y: ";
cin >> y;
if (y == 0)
{
cout << "Value of Y cannot be 0" << endl;
abort();
}
cout << x << "/" << y << ": " << x / y << endl;
}
return 0;
}
运行输出:
prejudice@prejudice-VirtualBox:~/Cplus_learning/bin$ ./abort
Input the value of x: 2
Input the value of y: 3
2/3: 0.666667
Input the value of x: 4
Input the value of y: 0
Value of Y cannot be 0
已放弃 (核心已转储)