通过使用const
限定符,假设变量是只读的。 例如,标记为const
的int
不能分配给:
const int number = 5; //fine to initialize
number = 3; //error, number is const
乍一看,这使得修改number
的内容变得不可能。 不幸的是,其实是可以做到的。 例如,可以使用CONST_CAST
(*CONST_CAST
)。 这是未定义的行为,但这不能保证number
实际上不会被修改。 它可以导致程序崩溃,但也可以简单地修改值并继续。
有可能使修改一个变量变得不可能吗?
可能需要这样做的原因可能是出于安全考虑。 一些非常有价值的数据不能被更改,或者发送的一段数据不能被修改,这可能是最重要的。
不,这不是一种编程语言所关心的问题。 任何“访问”保护都只是表面的,只存在于编译时。
如果您具有相应的权限,则始终可以在运行时修改计算机的内存。 您的操作系统可能会为您提供保护内存页的工具,例如Windows下的VirtualProtect()。
(请注意,如果“攻击者”有权限,他可以使用相同的工具恢复访问。)
此外,我认为可能有硬件解决方案。
还有一个选项是加密所讨论的数据。 然而,这似乎是一个鸡和蛋的情况,因为用于加密和解密的私钥也必须存储在内存中的某个地方(使用仅限软件的解决方案)。
常量x
的含义基本上是:
嘿编译器,请防止我在这个改变x
的作用域中随便编写代码。
这与:
嘿,编译器,请防止对此范围内的x
进行任何更改。
即使您自己没有编写任何const_cast
,编译器也不会假定const
的实体不会更改。 具体地说,如果您使用函数
int foo(const int* x);
编译器不能假定foo()
没有更改x
指向的内存。
变量变化。。。 因此,很自然地,一种防止这种情况的方法就是使用没有存储在变量中的值。 你可以通过使用。。。
enum:int{number=1}
。#define NUMBER 1
<-不推荐内联int get_number(){return 1;}
正如@SebastianHoffman所建议的那样,典型的平台允许将某个进程的虚拟内存空间标记为只读,这样,试图更改它将导致进程的访问冲突信号,并暂停其执行。 这不是语言本身内的解决方案,但它通常是有用的。 示例:当您使用字符串文字时,例如:
const char* my_str = "Hello world";
const_cast<char*>(my_str)[0] = 'Y';
您的进程可能会失败,并显示如下消息:
Segmentation fault (core dumped)
如果您在编译时了解该程序,则可以将数据放在只读内存中。 当然,有人可以绕过这一点,但安全是关于层次而不是绝对的。 这就更难了。 C++对此没有概念,因此您必须检查生成的二进制文件以查看是否发生了这种情况(这可以作为构建后检查编写脚本)。
如果您在编译时没有这个值,那么您的程序就依赖于能够在运行时更改/设置它,因此您根本无法阻止它的发生。
当然,您可以使用const
这样的工具来使它变得更困难,因此代码是在假定它不会更改的情况下编译的/程序员很难意外地更改它。
您可能还会发现constexpr
是一个有趣的工具,可以在这里进行研究。