c++ - 为什么重新声明 std::cout 会导致段错误?

标签 c++ linux g++

我正在用这段代码测试 C++。我在 Ubuntu 18.10 版上使用 GCC 8.3.0 版编译。

#include <ostream>
namespace std{
    extern ostream cout;
};
int main(){
    std::cout << "Hello world\n";
}

代码编译没有问题。但是,执行时,程序打印出:

Segmentation fault (core dumped)

这是为什么?

最佳答案

首先,我们已经说明了您的程序具有未定义的行为,因为您不允许在命名空间 std 中声明内容像这样。仅允许使用工具链。

通常当你的程序有 UB 时,比如读取内存的一些随机部分或混淆优化器,所有的赌注都没有了,我们甚至不会费心去弄清楚为什么我们看到了一些特定的结果。但是,在本例中,它比这要简单一些。

例如,在 libstdc++v3(您正在使用的)中,取决于某些配置 the actual stream declarationsin namespace std::__8 出于版本控制原因,其中 __8是一个内联命名空间。你的extern声明不是,因此它与真实的原始声明不匹配。这可能导致 a linker error ,因为新添加的声明实际上并没有与任何存在的对象结合。

在其他配置中,conflicting visibility settings声明上的错误可能会进一步混淆链接器并导致运行时的段错误。 真正确定原始声明对您来说是什么样子的唯一方法是观察程序的预处理源代码 #include <iostream>在您的计算机上(这并不难;使用 g++ -E !)并查看它如何针对您的特定配置结束。

这个故事的寓意是,尽管浏览 cppreference.com 会让您相信 cout开始它的生活很简单:

namespace std {
   ostream cout(/* some args */);
}

…现实往往更复杂,您的重新声明没有考虑任何并发症,其中一些并发症可能会以产生您观察到的结果的方式违反规则。

关于c++ - 为什么重新声明 std::cout 会导致段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57020706/

相关文章:

c++ - 使用 winsock 发送 POST 数据(并使用 PHP 服务器端脚本接收它们)

c++ - MSVC++ 2013 中的资源

linux - awk中的键值对

linux - 如何在 bash 中精确打印一些文本

linux - bash 合并文件中的行

c++ - 防止 g++ 添加额外的 elf 部分

c++ - g++ 的 std::list::sort 是否使迭代器无效?

c++ - QLabel 上的 QPixmap 显示不正确

c# - C#/WPF 项目中的类在 C++/CLI 项目中不起作用

linux - 使用 g++ 的符号可见性