关于全局常量写的Segfault

时间:2014-12-22 02:19:41

标签: c++

请考虑以下代码:

const int x = 5;     
int main() {
    int* p = const_cast<int*>(&x);
    *p = 10;
    return 0;
}

http://ideone.com/lbcWdT

它会导致分段错误。现在考虑一下:

int main() {
    const int x = 5;
    int* p = const_cast<int*>(&x);
    *p = 10;
    return 0;
}

http://ideone.com/l8rcDq

工作正常。

  1. 为什么仅在全局常量写入时引发Segfault?
  2. 为什么会发生Segfault?

3 个答案:

答案 0 :(得分:5)

在这两种情况下都有未定义的行为:只有当对象实际上确实引用了一个可变对象时才允许抛出const。您不能抛弃const以获取作为const对象开始生命的对象。这些对象可能存在于只读存储器中(在第一个示例中显然就是这种情况),但这并不是必需的(正如您的第二个示例所示)。

答案 1 :(得分:1)

当你使用const时,你告诉编译器它允许更大的自由来对象做什么以换取你的承诺,你永远不会尝试改变它。当你违背这个承诺时,你就会进入未定义行为的土地。

有时编译器会以这样的方式创建代码来响应,你可以抛弃const,一切都会好的 - 就好像它从来都不是const一样。但是,这就像你的代码有效“幸运”。

const抛弃在一个不可变的对象上永远不会安全。

答案 2 :(得分:0)

C ++运行时有两种类型的内存,只读和读写。编译时常量被放入只读内存中,即使使用强制转换也无法更改。这里的const是硬件限制,并编写段错误。自动变量(函数范围变量)放在堆栈上,即读写存储器。这里的const是一个软件限制,绕过限制使写入成为可能。

只读与读写内存的最简单示例是字符串常量:

char *p = "string"; p[0] = 'a'; // segfault
char q[] = "string"; q[0] = 'a'; // "atring"