为什么以这种方式访问联合中的指针会导致分段错误?
Why does access a pointer in a union this way cause segmentation fault?
为什么下面的代码会导致段错误?
#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
访问 u.str_ptr
是不合法的,除非它是联盟中的 the last member set。但是联合中的最后一个成员集是 boolean
,因为具有一个未指定值的初始化列表设置了第一个成员。
参见 struct and union initialization 下的 "member lifetime"。
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");
new 返回的指针被隐式转换为第一个成员的类型,即 bool
类型。由于 C++ 允许此转换,因此不会发生错误。
// effectively what is happening.
U u{ new std::string("A") != 0 };
使用这样的联合时,最好是显式地直接分配给成员。但是,如果您真的想这样做,只需将 str_ptr
作为第一个成员即可。
为什么下面的代码会导致段错误?
#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
访问 u.str_ptr
是不合法的,除非它是联盟中的 the last member set。但是联合中的最后一个成员集是 boolean
,因为具有一个未指定值的初始化列表设置了第一个成员。
参见 struct and union initialization 下的 "member lifetime"。
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");
new 返回的指针被隐式转换为第一个成员的类型,即 bool
类型。由于 C++ 允许此转换,因此不会发生错误。
// effectively what is happening.
U u{ new std::string("A") != 0 };
使用这样的联合时,最好是显式地直接分配给成员。但是,如果您真的想这样做,只需将 str_ptr
作为第一个成员即可。