14

是否应该set_terminate/get_terminate为 C++ 2011 或 C++ 2003 中的多个线程设置不同的终止异常处理器?

例如,如果我有程序并将终止处理程序设置为func_1;然后我启动 3 个线程。什么是新线程中的终止处理程序?如果在每个线程中我将终止处理程序设置为func_2在第一个线程中,func_3在第二个线程中等等。

N3242(C++ 2011 草案)[handler.functions][support.exception]/[exception.terminate]

PS:对于这些标准的任何流行实现,您可以回答 C++2011 或 C++2003

PPS:对此有 FCD 评论... C++ FCD 评论状态 Rev. 5 N3249 (2011)

GB 71    18.6.2.4 / 18.8.2.2 / 18.8.3.2   

std::set_new_handler(), std::set_unexpected(), ,的线程安全性std::set_terminate()未指定,使得函数无法以线程安全的方式使用。

必须指定函数的线程安全保证,并且应该提供新的接口,以便以线程安全的方式查询和安装处理程序。

LWG 1365 接受修改

见论文 N3189

4

4 回答 4

10

17.6.4.7p4 说:

调用set_*andget_*函数不会引起数据竞争。对任何函数的调用应与对同一函数和相应函数set_*的后续调用同步。set_*get_*

这强烈暗示set_*andget_*函数在相同的全局状态下运行,即使从不同的线程调用也是如此。18.8.3 下的所有段落都讨论了“当前处理函数”,没有其他提及线程;这表明处理函数是整个程序的一个属性;同样,17.6.4.7 具有:

2 - C++ 程序可以在执行期间安装不同的处理函数 [...]
3 - C++ 程序可以通过调用以下函数来获取指向当前处理函数的指针 [...]

这些段落讨论了程序上下文中的当前处理函数,表明它是程序范围的而不是线程本地的。

于 2013-03-12T16:52:55.667 回答
4

在标准中它说

18.8.3.2 set_terminate [set.terminate]

terminate_handler set_terminate(terminate_handler f) noexcept;

1 效果:将 f 指定的函数建立为当前处理函数,用于终止异常处理。

[[noreturn]] void terminate() noexcept;

2 效果:调用当前的 terminate_handler 函数。[ 注意:在这种情况下,默认的 terminate_handler始终被视为可调用的处理程序。——尾注]

您可以看到它terminate() 调用了当前的终止处理程序,在该set_handler部分中它非常清楚地表明它用于终止进程。当所有其他异常处理失败时,无论从哪个线程运行,都会调用它。

只有一个终止处理程序,它总是从程序终止的任何地方调用。

于 2013-03-12T16:54:09.087 回答
3

该标准没有具体说明;[set.terminate]仅状态

[...] 用于终止异常处理的当前处理函数。

但没有提到“当前”是全局的还是每个线程的。所以这取决于实施。

例如,在 MSVC++ 中: https ://msdn.microsoft.com/en-us/library/t6fk7h29.aspx

在多线程环境中,终止函数是为每个线程单独维护的。每个新线程都需要安装自己的终止函数。因此,每个线程都负责自己的终止处理。

于 2018-02-14T04:11:20.267 回答
1

C2003 没有线程,任何线程支持都是供应商扩展,因此只有供应商提供的文档才有答案。如果处理程序是每个线程的,则文档应该这样说。我知道没有任何实现可以做到这一点。

C++2011 没有说明终止处理程序的每线程性质。每个线程都维护它没有什么意义,因为你不能在 C++11 中杀死一个线程。还有一个很好的理由(google kill+thread+c++11)。所以无论你做什么,程序都必须终止。看起来有不同的方法来终止程序,具体取决于请求它的线程不是任何人都需要的功能。

于 2013-03-12T17:27:49.510 回答