c++ - set_new_handler 是否将 new_handler 存储在线程本地存储中?
问题描述
有人询问set_new_handler
在多线程环境中是否安全。我想知道 C++ 11 及更高版本的 C++ 标准库实现是否使用该thread_local
功能来存储std::new_handler
. 如果实现不使用thread_local
,为什么不呢?这似乎使该功能在多线程程序中更加强大。
我也没有真正看到set_new_handler
重载new
和设置 astd::new_handler
并创建(并拥有对)一个对象的类的工作方式,该对象也重载new
并设置自己的std::new_handler
. 如果拥有类具有获取/释放内存的选项,而拥有的对象决定调用中止/终止,我希望这将特别令人震惊。
我希望通常的建议是使用nothrow
version of new
and forget set_new_handler
。如果这是一个普遍的观点,为什么set_new_handler
标准库中没有弃用的功能?
解决方案
new_handler
不是,也从未期望是线程本地构造。它始终是全球性的,这是设计使然。
新的处理程序旨在设置一次并单独放置;它不适用于单个执行线程本地的临时更改。您可以通过创建一个新的处理程序来为自己构建这样的工具,该处理程序将其操作推迟到thread_local
您的代码可以设置的变量。但 C++ 新的处理程序特性本身并不适用于此类用例。
现在,可以说这是一项遗留决定。C++98/03的内存模型没有考虑线程的可能性。因此,任何 C++11 之前的线程实现基本上都是自己决定哪些操作是线程安全的,哪些是线程本地的,等等。决定将 new-handler 实现为全局构造的实现与使其成为每个线程的实现一样正确。事实上,实现可能在某个时候选择了全局选项,而 C++11 刚刚采用了它。将其更改为线程本地会破坏人们的代码。
但同时,新处理程序的重点是允许用户更改分配失败的默认处理方式。默认错误处理不是线程局部概念;这是整个程序通用的东西。与终止函数等非常相似,恰好有一个预期会被使用。
简而言之,使用类本地新处理程序的代码在某种程度上总是错误的,即使在 C++98/03 时代也是如此。只是在 C++11 标准化线程之前,它是你可以摆脱的(至少就标准而言)。并且它不会被弃用,因为它对其预期目的很有用。nothrow
只在本地有用;set_new_handler
在全球范围内有用。
推荐阅读
- php - 从 PHP 获取 highcharts 图像 URL
- javascript - 在浏览器中使用带有导入的 es6 样式类的 TypeScript 转译代码,而无需额外的转译步骤?
- r - R如何排列数据帧的所有行,以便在列表中返回所有可能的行组合?
- python - Python unix时间戳没有转换但似乎很有价值
- jenkins - Jenkins 工作触发了两次
- excel - 在 VBA 中使用“sumif”和“.formula”和变量
- keycloak - 为什么'id'在keycloak中被称为'sub'?
- javascript - 无法链接 CSS 和 Javascript
- oauth-2.0 - IdentityServer4 丢失登录会话
- gwt - 带有类型化响应的 JsonpRequestBuilder 抛出 InCompatibleClassChangeError