set_new_handler and errno

set_new_handler and errno

本文关键字:errno and new set handler      更新时间:2023-10-16

如果您使用 set_new_handler 并且调用了您的处理程序函数,是否保证errno被设置,就像从 malloc 返回 0 一样?还是使用strerror(ENOMEM)更好? errno适用于Microsoft C++和 GCC,但这仍然留下了它是否得到保证的问题。

我认为errno不足以检测动态内存分配故障。查看 N3337,特别是 3.7.4.1 分配函数

2 [...]即使请求的空间大小为零,请求也可能失败。 如果请求成功,则返回的值应为非空指针值 (4.10) p0,不同于任何 以前返回的值 P1,除非该值 P1 随后传递给运算符 delete。这 取消引用作为零大小请求返回的指针的影响是不确定的。35

3 分配存储失败的分配函数可以调用 当前安装的新处理程序函数 (18.6.2.3)(如果有)。[ 注:A 程序提供的分配函数可以获取 当前安装new_handler使用 std::get_new_handler 函数 (18.6.2.4)。—尾注 ] 如果声明了分配函数 使用非抛出异常规范 (15.4) 无法分配 存储,它应返回一个空指针。任何其他分配函数 未能分配存储的应仅通过抛出来指示故障 与类型的处理程序 (15.3) 匹配的类型异常 标准::bad_alloc (18.6.2.1).

脚注35(这只是指示性的,非规范性的):

35) 目的是通过调用 std::malloc() 或 std::calloc() 来实现运算符 new(),因此规则实质上是 一样。C++与 C 的不同之处在于要求零请求返回非空指针。

现在,转到 C 标准草案,N1570 并查看 7.5 错误<errno.h>

3 初始线程中 errno 的值在程序启动时为零(初始值为 其他线程中的 errno 是一个不确定的值),但永远不会被任何库设置为零 function.202) errno 的值可以通过库函数调用设置为非零值 是否存在错误,前提是 errno 的使用未记录在 本标准中对功能的描述。

似乎errno可能由malloc故障设置,但这不是必需的。

此外,N1570的7.22.3内存管理功能没有指定malloc或朋友需要设置errno

我的建议是坚持标准保证的内容并使用new抛出的异常(std::bad_alloc)(即不使用无抛出new)。

不需要

new(或malloc,就此而言)设置errno。 两者都有明确定义的错误报告语义(抛出std::bad_alloc或返回空指针),这不涉及errno。 (从实现质量的角度来看,我不希望允许newmalloc修改errno。 不遵守 Posix 要求。