【问题标题】:Why does access a pointer in a union this way cause segmentation fault?为什么以这种方式访问​​联合中的指针会导致分段错误?
【发布时间】:2017-03-02 06:53:29
【问题描述】:

为什么下面的代码会导致分段错误?

#include <string>

union U {
    bool boolean;
    double number;
    std::string* str_ptr;
};

int main()
{
    U u{new std::string("A")};
    delete u.str_ptr;
    return 0;
    // return u.str_ptr->compare("A");
}

我应该说,如果我代替 return 语句尝试以其他方式访问指针似乎并不重要。例如。将 delete u.str_ptr; return 0; 替换为 return u.str_ptr-&gt;compare("A"); 我仍然遇到分段错误。

如果这是特定于编译器的,我使用的是g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609

【问题讨论】:

    标签: c++ g++-5


    【解决方案1】:

    访问u.str_ptr 是不合法的,除非它是联合中的the last member set。但是联合中的最后一个成员集是boolean,因为具有一个未指定值的初始值设定项列表设置了第一个成员。

    请参阅struct and union initialization 下的“成员生命周期”。

    【讨论】:

    • 您引用了错误语言的参考。幸运的是,在撰写本文时 (en.cppreference.com/w/cpp/language/union) 在 C++ 中也是如此(模指定的初始化程序,不存在)。
    • 您更改了链接,但保留了引用...该页面上不存在...
    【解决方案2】:

    U u{new std::string("A")}; 不会像你想的那样,因为你没有说什么特别的,它用调用new 的值初始化第一个成员。如果要设置正确的成员,请使用以下内容:

    U u{.str_ptr=new std::string("A")};
    

    ---编辑---

    这是gcc 扩展,标准规定当使用大括号封闭的初始化程序初始化联合时,大括号应仅包含联合的第一个非静态数据成员的初始化子句。时间>。然后用标准你只能这样做:

    U u;
    u.str_ptr = new std::string("A");
    

    【讨论】:

    • 这还能编译吗?它看起来像 C99 指定的初始化程序,它不是 C++ 的一部分。
    【解决方案3】:

    new 返回的指针被隐式转换为第一个成员的类型,即类型bool。由于 C++ 允许这种转换,因此不会发生错误。

    // effectively what is happening.
    U u{ new std::string("A") != 0 };
    

    当使用这样的联合时,最好是明确的并直接分配给成员。但是如果你真的想这样做,就让str_ptr成为第一个成员。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-10
      • 2013-10-25
      • 2018-02-20
      • 1970-01-01
      • 2011-11-22
      • 2017-08-18
      相关资源
      最近更新 更多