为什么以这种方式访问​​联合中的指针会导致分段错误?

时间:2016-10-20 10:17:03

标签: c++ g++-5

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

#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->compare("A");我仍然会遇到分段错误。

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

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:1)

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

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

--- --- EDIT

这是gcc扩展,标准说当使用大括号括起初始值设定项初始化union时,大括号应仅包含union的第一个非静态数据成员的initializer子句。 。然后用标准你只能这样做:

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

答案 2 :(得分:0)

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

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

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