[英]How will _Exit behave in a C++ program?
C99 offers the _Exit
function, which exits "immediately", although it
does
may close file descriptors. C99提供了
_Exit
功能,“立即”退出,虽然
它
可能会关闭文件描述符。 Unix/POSIX extends this behavior by mandating the closing of all fd's without flushing (and offers the synonym _exit
). Unix / POSIX通过强制关闭所有fd而不刷新来扩展此行为(并提供同义词
_exit
)。
Will these functions call destructors for static
objects when called from a C++ program? 当从C ++程序调用时,这些函数会调用
static
对象的析构函数吗? Does the C++ standard make any guarantees about _Exit
? C ++标准是否对
_Exit
做出任何保证?
(Inspired by this question ; I suddenly wondered what happens in the typical fork
- exec
- _exit
idiom in C++.) (受这个问题的启发;我突然想知道在C ++中典型的
fork
- exec
- _exit
成语会发生什么。)
First, no form of program exit will automatically call destructors for heap objects (implied in ISO/IEC 14882:1998(E) 12.4.10). 首先,任何形式的程序退出都不会自动调用堆对象的析构函数(隐含在ISO / IEC 14882:1998(E)12.4.10中)。
Calling exit()
will not call destructors for objects with automatic duration, as it does not return through their enclosing scopes (3.6.1.4). 调用
exit()
不会为具有自动持续时间的对象调用析构函数,因为它不会通过其封闭范围返回(3.6.1.4)。 However, destructors for static objects will be called, in reverse order of construction (18.3.8). 但是, 将按照构造的相反顺序调用静态对象的析构函数(18.3.8)。
Calling abort()
does not call any destructors for any type of object, nor does it call atexit()
registered functions (18.3.3). 调用
abort()
不会为任何类型的对象调用任何析构函数,也不会调用atexit()
注册的函数(18.3.3)。 The C++ standard copy I have here is a bit dated and does not mention _exit
or _Exit
directly, but I'd imagine that, if present, they should behave the same - that is, not calling any destructors. 我在这里的C ++标准副本有点过时,并没有直接提到
_exit
或_Exit
,但我想,如果存在,它们的行为应该相同 - 也就是说,不要调用任何析构函数。 In particular, in the C99 standard, _Exit()
skips atexit
handlers (it is implementation defined whether stream buffers are flushed, open streams are closed, or temporary files removed). 特别是,在C99标准中,
_Exit()
跳过atexit
处理程序(实现定义是否刷新流缓冲区,关闭打开的流,还是删除临时文件)。
Further note that abort()
can be cancelled by trapping signal SIGABRT
(ISO/IEC 9899:1999 (E) 7.20.4.1.2 - I only have C99 here but I expect it would be the same in the version referenced by C++). 进一步注意,可以通过捕获信号
SIGABRT
来取消abort()
(ISO / IEC 9899:1999(E)7.20.4.1.2 - 我这里只有C99但我希望它在C ++引用的版本中是相同的)。 _Exit()
cannot. _Exit()
不能。
On a more practical note, on most unix implementations of abort()
and _exit()
, abort()
raises a SIGABRT
while _exit()
simply calls an operating system call to terminate the process immediately. 更实际的是,在
abort()
和_exit()
大多数unix实现中, abort()
引发SIGABRT
而_exit()
只是调用操作系统调用来立即终止进程。 This means that the main differences are: 这意味着主要的区别是:
_exit()
_exit()
指定退出代码 abort()
may be trapped by a signal handler abort()
可能被信号处理程序捕获 abort()
may result in a core dump or similar abort()
可能会导致核心转储或类似情况 In a fork()/exec()
pattern, _exit()
would probably be preferable, to avoid the possibility of core dump. 在
fork()/exec()
模式中, _exit()
可能更可取,以避免核心转储的可能性。
It simply doesn't exist in standard C++, so there are no guarantees. 它在标准C ++中根本不存在,因此无法保证。
It is planned for inclusion in C++0x. 拟列入的C ++ 0x。 That specifies (§18.5):
这指定(§18.5):
The function _Exit(int status) has additional behavior in this International Standard:
函数_Exit(int status)在本国际标准中有其他行为:
— The program is terminated without executing destructors for objects of automatic, thread, or static storage duration and without calling functions passed to atexit() (3.6.3).
- 程序终止而不执行自动,线程或静态存储持续时间对象的析构函数,并且不调用传递给atexit()的函数(3.6.3)。
Followup: 跟进:
ISO approved C++0x on August 12, 2011. ISO于2011年8月12日批准了C ++ 0x。
Technically, _Exit
is not defined by the C++ standard, so you can't even call it from a 100% portable C++ program. 从技术上讲,
_Exit
不是由C ++标准定义的,因此您甚至无法从100%可移植的C ++程序中调用它。 The C++03 standard incorporates by reference the C89 standard (aka C90 or ANSI C), whereas _Exit
is only defined in the newer C99 standard. C ++ 03标准通过引用并入C89标准(又名C90或ANSI C),而
_Exit
仅在较新的C99标准中定义。 I'm not sure which version of C the upcoming C++0x standard incorporates, but I would guess that it's based on C99. 我不确定即将推出的C ++ 0x标准包含哪个版本的C,但我猜它是基于C99的。
In any case, though, here are the relevant clauses from the relevant language standards: 但无论如何,这里是相关语言标准的相关条款:
_Exit
is not guaranteed to close file descriptors. _Exit
不保证关闭文件描述符。 From C99 §7.20.4.4/2 (emphasis mine): 从C99§7.20.4.4/ 2(强调我的):
The
_Exit
function causes normal program termination to occur and control to be returned to the host environment._Exit
函数会导致正常的程序终止,并将控制权返回给主机环境。 No functions registered by theatexit
function or signal handlers registered by thesignal
function are called.没有通过注册的功能
atexit
由注册的函数或信号处理signal
函数被调用。 The status returned to the host environment is determined in the same way as for theexit
function (7.20.4.3).返回到主机环境的状态的确定方式与
exit
功能(7.20.4.3)相同。 Whether open streams with unwritten buffered data are flushed, open streams are closed, or temporary files are removed is implementation-defined.是否刷新具有未写入缓冲数据的开放流,关闭打开流,或者删除临时文件是实现定义的。
Recall that implementation-defined means that the implementation (that is, the compiler toolchain and runtime environment) can choose to do whatever it wants, but it must document what it does . 回想一下, 实现定义意味着实现(即编译器工具链和运行时环境)可以选择做任何想做的事情,但它必须记录它的作用 。
From C++03 §3.6.3/1: 来自C ++03§3.6.3/ 1:
Destructors (12.4) for initialized objects of static storage duration (declared at block scope or at namespace scope) are called as a result of returning from main and as a result of calling
exit
(18.3).用于静态存储持续时间的初始化对象的析构函数(12.4)(在块作用域或命名空间作用域中声明)作为从main返回并由于调用
exit
(18.3)的结果而被调用。 These objects are destroyed in the reverse order of the completion of their constructor or of the completion of their dynamic initialization.这些对象以其构造函数完成或动态初始化完成的相反顺序销毁。 If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized.
如果对象是静态初始化的,则对象的破坏顺序与对象动态初始化的顺序相同。 For an object of array or class type, all subobjects of that object are destroyed before any local object with static storage duration initialized during the construction of the subobjects is destroyed.
对于数组或类类型的对象,在销毁子对象构造期间初始化静态存储持续时间的任何本地对象之前,将销毁该对象的所有子对象。
§3.6.3/4: §3.6.3/ 4:
Calling the function
调用函数
void abort();
declared in
<cstdlib>
terminates the program without executing destructors for objects of automatic or static storage duration and without calling the functions passed toatexit()
.在
<cstdlib>
声明的终止程序,不会为自动或静态存储持续时间的对象执行析构函数,也不会调用传递给atexit()
的函数。
Practically, in most implementations, global object destructors are implemented via atexit
, so what you will see is that _Exit
will not call the destructors for global objects, although this behavior is not guaranteed (since _Exit
and C++ are not guaranteed to both exist in the same language). 实际上,在大多数实现中,全局对象析构函数是通过
atexit
实现的,所以你会看到_Exit
不会为全局对象调用析构函数,虽然这种行为不能得到保证(因为_Exit
和C ++不能保证都存在于同一种语言)。
Note that while C++ does not specify _Exit
and C99 leaves it implementation-defined whether it flushes buffers, POSIX requires that it not flush buffers (since this would break the main usage of _exit
/ _Exit
, ie handling failure of execve
after fork
). 请注意,虽然C ++没有指定
_Exit
而C99让它实现定义是否刷新缓冲区,但POSIX 要求它不刷新缓冲区(因为这会破坏_exit
/ _Exit
的主要用法,即在fork
之后处理execve
失败)。 As POSIX does not align itself with C++ standards or defer to them on anything, I think it's very unlikely that a future version of the C++ standard would try to change any of this. 由于POSIX没有与C ++标准保持一致或者在任何事情上遵守它们,我认为未来版本的C ++标准不太可能试图改变这一点。 It will probably either leave
_Exit
unspecified or specify that it's implementation-defined. 它可能要么未指定
_Exit
要么指定它是实现定义的。
C++0x defines a new function called std::quick_exit that terminates a process without calling any destructors. C ++ 0x定义了一个名为std :: quick_exit的新函数,它终止进程而不调用任何析构函数。 Just checked, g++-4.4.5 already provides it.
刚刚检查过,g ++ - 4.4.5已经提供了它。
Calling of static destructors is defined in terms of atexit. 静态析构函数的调用是根据atexit定义的。 _exit (or _Exit) is defined not to run atexit handlers.
_exit(或_Exit)定义为不运行atexit处理程序。 So static destructors should not be called by any implementation.
因此,任何实现都不应调用静态析构函数。
Automatic destructors are not even called when calling exit(). 调用exit()时甚至不调用自动析构函数。
So any sane definition of _Exit semantics for C++ would not run destructors. 因此,C ++的_Exit语义的任何理智定义都不会运行析构函数。
I did a quick test with gcc on Mac OS and my destructors didn't get called. 我在Mac OS上用gcc进行了快速测试,我的析构函数没有被调用。
struct A
{
~A()
{
puts("A::~A");
}
};
A globalA;
int main()
{
A localA;
_exit(0); // or _Exit(0)
return 0;
}
exit(0)
on the other hand calls globalA
's destructor. 另一方面,
exit(0)
调用 globalA
的析构函数。
fork()
, exec()
, and _exit()
are all defined by POSIX and they pre-date C99's _Exit()
by many years. fork()
, exec()
和_exit()
都是由POSIX定义的,它们将C99的_Exit()
预定多年。 Programs that use fork
/ exec
/ _exit
are not portable to every system that supports C++. 使用
fork
/ exec
/ _exit
程序不能移植到支持C ++的每个系统。
With regard to _exit()
specifically, it is an operating system call that (under POSIX) will close files and terminate the process directly (but not necessarily quickly). 特别是关于
_exit()
,它是一个操作系统调用(在POSIX下)将关闭文件并直接终止进程(但不一定很快)。 This would bypass any C++ mechanisms for calling destructors. 这将绕过用于调用析构函数的任何C ++机制。
Even with _Exit()
or similar being provided by C++0x, I doubt if there would be much reason to use that in conjunction with fork. 即使C ++ 0x提供了
_Exit()
或类似的东西,我怀疑是否有太多理由将它与fork结合使用。 It likely just provides broader portability for a "quick-exit" in other contexts. 它可能只是为其他环境中的“快速退出”提供了更广泛的可移植性。 That functionality is already covered by
_exit()
if you are using the POSIX API. 如果您使用的是POSIX API,则
_exit()
已涵盖该功能。
Program termination is addressed in C++2003 section [3.6.3]. 程序终止在C ++ 2003部分[3.6.3]中解决。 It says that static objects are destructed implicitly when
main()
returns and when exit()
is called. 它表示当
main()
返回和调用exit()
时,静态对象被隐式地破坏。 It also says that such objects are NOT destructed when abort()
is called. 它还说当调用
abort()
时不会破坏这些对象。 _exit()
isn't addressed in the C++ 2003 standard, but the fact that it is meant to bypass language-specific cleanup is described in the POSIX documentation. _exit()
未在C ++ 2003标准中得到解决,但POSIX文档中描述了它旨在绕过特定于语言的清理的事实。 That effect is further substantiated by what is stated and by what is NOT stated in the C++ standard. 通过陈述的内容和C ++标准中未说明的内容进一步证实了这种效果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.