我知道全局const存储在.rodata
中另外,我知道函数中声明的变量存储在堆栈中。但是因为const应该只是只读的,所以堆栈中是否有特殊的部分?如何控制对它们的访问?
答案 0 :(得分:4)
你真正应该知道的是:如果一个对象被声明为const,编译器将不会轻易让你尝试修改它,如果你绕过编译器,那么任何修改对象的尝试都是未定义的行为。而已。没有其他的。忘记.rodata或你学到的任何东西,重要的是修改const对象的尝试是未定义的行为。
我的意思是“编译器不会让你”并绕过它:
const int x = 5;
x = 6; // Not allowed by compiler
int* p = &x; *p = 6; // Not allowed by compiler
int* p = (int*)&x; *p = 6; // Allowed by compiler, undefined behaviour.
执行最后一个语句可能会崩溃,或者将x更改为6,或者将x更改为999,或保持x不变,或使其表现为精神分裂的方式,其中有时为5,其他时间为6,包括x == x是假的。
答案 1 :(得分:1)
当const
局部变量以恒定的时间点初始化时,它可能根本不存储。请考虑以下代码:
int foo(int param)
{
const int value = 10;
return param + value;
}
optimizing compiler很可能会生成汇编代码,例如add
操作,其中value
由10
字面值替换。
除此之外,许多编译器会将它们放在堆栈框架上,就像#34;普通"自动变量,因此您可以获得的任何保护都是由编译器本身完成的。
答案 2 :(得分:0)
不,一般来说,没有任何"常数"堆栈的区域。但那没关系,因为const
的真正含义是"我保证不会尝试修改这个"。这并不意味着将它放在只读存储器中,这样我们就可以保证在遇到错误时会出现总线错误。
答案 3 :(得分:0)
没有只读堆栈段,因为它必须是可写的初始化,每次进入函数时都会发生。每个函数调用都会产生不合理的开销,要求内核更改页面保护,初始化变量,然后将其更改回来。
rodata起作用,因为静态分配的const变量只初始化一次。