是否打印空指针未定义行为?

Posted

技术标签:

【中文标题】是否打印空指针未定义行为?【英文标题】:Is printing a null-pointer Undefined Behavior? 【发布时间】:2014-06-10 14:47:25 【问题描述】:

在研究 this question 的示例代码时,我认为它是未定义的行为,它阻止了 std::cout 的后续使用打印。但事实证明,attempting to print a null pointer caused std::ios_base::badbit and std::ios_base::failbit to be set in its stream state 是其无法运行的真正原因。因此,我现在很好奇(尝试)打印空指针是否真的未定义行为。所以这是我的问题:

    打印空指针是否为未定义行为?如果是这样,导致这种情况的流插入器是什么?我很确定插入器足够聪明,不会取消引用空指针。

    我还想知道为什么插入器在这种情况下遇到空指针时会设置其错误掩码(特别是badbit)。为什么不将其视为字符串文字的终止?

我手边没有标准,到目前为止我只找到一个不幸导致死链接的来源。

【问题讨论】:

libstdc++ 可能会在不需要时进行额外的nullptr 检查。程序seg faults 当你用 clang+libc++ 构建它时。但不是 clang+libstdc++ “我很确定插入器足够聪明,不会取消引用空指针。” - 通常,C++ 标准说明了编译器必须做什么,而其他任何事情,他们都不必做。在每次调用 operator<<(char *) 之前,它会减慢正确编码的程序进行额外的 NULL 检查。 @MattMcNabb:哈哈,当处理像 C++ I/O 流这样慢得可怕的东西时,我不认为空检查的速度是一个问题。 密切相关: ***.com/q/7019454/560648(几乎是骗子,tbh) 【参考方案1】:

gcc ostream.tcc 第 319 行:

template<typename _CharT, typename _Traits>
  basic_ostream<_CharT, _Traits>&
  operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
  
    if (!__s)
__out.setstate(ios_base::badbit);

gcc 只是执行标准不保证的检查,这很好,因为它无论如何都是未定义的。

【讨论】:

【参考方案2】:

basic_ostreamoperator&lt;&lt;(basic_ostream&lt;&gt;&amp;, const char*) 函数要求char* 不为空——它旨在打印指针指向的字符串。因此,将空的char* 发送到cout 是未定义的行为。 (参见 C++11 27.7.3.6.4/3“字符插入函数模板”)。

不过,basic_ostreamoperator&lt;&lt;(basic_ostream&lt;&gt;&amp;, const void*) 函数只是打印指针的值,因此空指针可以在重载时正常工作。

【讨论】:

如果您通过[ostream.inserters.character] 引用标准而不是通过27.7.3.6.4 引用标准,那么它更有可能在可能已重新编号的章节或章节的不同版本中仍然是有效参考。

以上是关于是否打印空指针未定义行为?的主要内容,如果未能解决你的问题,请参考以下文章

删除 null void* 指针是未定义的行为吗?

为啥在已删除指针上调用非虚拟成员函数是未定义的行为?

C++ 中的这种未定义行为是不是从悬空指针调用函数

别名可变原始指针 (*mut T) 会导致未定义的行为吗?

C ++中的内存泄漏“未定义行为”类问题吗?

成员函数指针值上的 Consexpr - 未定义的行为?