size_t结构非数组成员崩溃的强制转换
size_t cast of struct non-array member crashes
为什么在下面的代码中...
#include <iostream>
struct Foo
{
int a;
char b;
char c[1];
};
struct Bar
{
int a;
char b;
char c;
};
int main( int argc, char* argv[] )
{
std::cout << "Why does this work? " << (size_t) (((struct Foo*) 0)->c) << std::endl;
std::cout << "Why does this crash? " << (size_t) (((struct Bar*) 0)->c) << std::endl;
return 0;
}
。第二个size_t
操作是否会导致 SIGSEGV,而第一个操作不会?该程序的输出是:
Why does this work? 5
Segmentation fault (core dumped)
有人可以解释一下这行代码实际上在做什么吗?
(size_t) (((struct Foo*) 0)->c)
我以前从未见过这种语法,但对我来说,它看起来像是一对c
的转换——这是工作情况下的一个数组(我认为它退化为指针(——到一个size_t
。所以我认为代码将指针(即地址(投射到size_t
......这似乎是一个无害但毫无意义的操作......但在实践中,在工作情况下,代码不会返回无意义的值,而是可靠地返回似乎是c
偏移量的内容。为什么会这样?
(size_t) (((struct Bar*) 0)->c)
首先将等价于 NULL
的数 0
强制转换为 Foo*
。您唯一可以对空指针执行的操作就是将其与 NULL
进行比较。
但是,指针被->c
非法访问,产生未定义的行为。在这种情况下,程序可能会因 SIGSEGV 而崩溃,也可能不会崩溃。
代码是无稽之谈。也许意思是这样的:
(size_t) &(((struct Bar*) 0)->c)
这也是非法的,但它恰好是实现offsetof
宏的老式方法。
碰巧的是,当c
是一个数组时,数组到指针的转换有效地插入了一个隐式&
运算符,因此您得到的结果等效于 offsetof(Foo, c)
。
如果结构指针(结构 Foo*(0 的地址为 0x0000,而 c 是其数组的地址,则数组的地址 ((struct Foo*( 0(->c 位于 0x0005。 毕竟,数组的名称表示其地址。
正如 Griffiths 指出的那样,如果 Bar 的临时指针是 0x0000,并且 c 是其字符变量之一的地址,它会尝试从 0x0005 中获取 ((struct Bar*( 0(->c 的值,这显然从未被分配过,从而导致段错误。
它看起来只是在检查偏移量。 如果你要对它进行指针数学运算,最好实际分配结构的实例;或者像potatoswatter指出的那样使用offsetof(Foo,c(。
- 将方法转换为调用该方法的成员函子对象会导致崩溃
- 逐字读取文本文件中的每一行并转换为 int(无限循环或崩溃?
- Qt-工作线程崩溃时将cv::Mat转换为QImage
- 具有重载类型转换运算符的函数对象崩溃
- size_t结构非数组成员崩溃的强制转换
- 将多面体转换为nef(违反访问)时,与CGAL崩溃
- 将MXArray转换为CV :: MAT时,程序会崩溃
- vtkProp::SafeDownCast() 在尝试转换 vtkactor 时崩溃
- 在CV :: MAT和Qimage之间进行转换会使程序崩溃
- 指针强制转换会导致 C++ 崩溃
- C++具有显式强制转换的代码,导致Visual Studio编译器崩溃
- 无法获得通过C++警告:(和崩溃后)已弃用从字符串常量到"char*"的转换 [-Wwrite-strings]
- 将指针类型转换为int会崩溃
- C++多个程序问题(rand、转换、崩溃)
- 为什么使用static_cast运算符的不安全强制转换不会崩溃
- 为什么我的C++程序在将 lambda 转换为函数指针时崩溃
- C++,从实用程序:string_t到标准::字符串的转换在返回时崩溃
- 火鸟在“UTF8 字符串转换为 wstring”时崩溃
- 将C++代码转换为C时程序崩溃
- 将uchar转换为int,然后转换为字符串会导致崩溃