在32位ubuntu虚拟机上尝试以下代码:
static int a[0x1f0fff];
cout << &a[0x600000] << endl;
cout << &a[0x800000] << endl;
cout << &a[0x8fff00000] << endl;
0x984a140
0xa04a140
0x7c4a140
真的很困惑,地址不会持续增加。
数组位于堆中,打印的是虚拟内存地址。是因为它超过了虚拟内存空间吗?
此外,根据another answer,最后两行代码索引到未分配的内存部分。为什么没有报告段错误?
答案 0 :(得分:3)
你的十六进制符号虽然华而不实,但只不过是一种混淆(尽管十六进制文字的类型推断规则与否定文字不同)。
您的代码的行为是未定义,但可能不是您可能认为的原因。
请注意&a[0x600000]
在获取地址之前,实际上并未尝试取消引用 a
中不存在的(0x600000)元素。编译器需要将表达式计算为a + 0x600000
。的但强>
设置指向不是数组a
中的元素的地址的指针,或超出该数组末尾的地址的指针是未定义的行为。因此,允许编译器输出任何内容。
答案 1 :(得分:2)
未定义的行为不是段错误。你希望获得segfault。有时你会得到鼻子恶魔。
为什么这种特殊行为? 32位无符号数学模型2 ^ 32。不保证会发生,但我很确定这是编译结果在这里做的。
答案 2 :(得分:1)
此外,根据另一个答案,最后两行代码索引到未分配的内存部分。为什么没有报告段错误?
访问数组越界是未定义的行为,这意味着任何事情都可能发生,这也意味着不能保证段错误 - 它可能发生一次,下次可能不会发生(&#39;为什么它被称为undefined)。