如果你使用set_new_handler
并且你的处理函数被调用,errno
保证被设置,它是从 0 返回的方式malloc
?还是更好用strerror(ENOMEM)
?errno
适用于 Microsoft C++ 和 GCC,但这仍然存在是否得到保证的问题。
2 回答
没有要求new
(或malloc
就此而言)设置errno
. 两者都有明确定义的错误报告语义(抛出std::bad_alloc
或返回空指针),不涉及errno
. (从实施质量的角度来看,我不希望new
或被malloc
允许修改errno
。不符合 Posix 要求。)
我认为errno
检测动态内存分配失败还不够好。查看 N3337,特别是3.7.4.1 分配功能:
2 [...] 即使请求的空间大小为零,请求也可能失败。如果请求成功,则返回的值应是一个非空指针值 (4.10) p0,不同于任何先前返回的值 p1,除非该值 p1 随后被传递给操作员删除。取消引用作为零大小请求返回的指针的效果是未定义的。35
3分配存储失败的分配函数可以调用当前安装的新处理函数 (18.6.2.3),如果有的话。[ 注意:程序提供的分配函数可以使用 std::get_new_handler 函数 (18.6.2.4) 获取当前安装的 new_handler 的地址。—尾注]如果使用非抛出异常规范(15.4)声明的分配函数未能分配存储,它应返回一个空指针。任何其他分配存储失败的分配函数只能通过抛出与 std::bad_alloc (18.6.2.1) 类型的处理程序 (15.3) 匹配的类型的异常来指示失败。
和脚注 35(这只是指示性和非规范性的):
35)意图是通过调用 std::malloc() 或 std::calloc() 使 operator new() 可实现,因此规则基本相同。C++ 与 C 的不同之处在于要求零请求以返回非空指针。
现在,前往 C 标准草案 N1570 并查看7.5 错误<errno.h>
:
3程序启动时初始线程中errno的值为零(其他线程中errno的初始值为不确定值),但绝不会被任何库函数设置为零。202)errno的值可以设置为如果在本国际标准的函数描述中未记录 errno 的使用,则无论是否存在错误,库函数调用都为非零。
似乎errno
可能由malloc
失败设置,但这不是必需的。
另外N1570的7.22.3内存管理功能也没有规定malloc
或者朋友需要设置errno
。
我的建议是坚持标准保证并使用std::bad_alloc
抛出的异常 ( ) new
(即不使用 no-throw new
)。