c++ 编译器是否保护常量内存地址免受任何更改?



我想证明没有什么已知的(受保护的内存地址(,整个故事只是关于编译器,操作系统,或者托管应用程序正在运行的任何应用程序,只需检查托管应用程序发送到其高级进程的读取和写入请求,这个高级应用程序或任何你称之为它的东西,决定这个子进程是否有权读取或写入这个特定的内存位置,但此C ++代码在此本质上不起作用,那么为什么:

#include <iostream>
int main()
{
const int x = 10;
std::cout << &x << std::endl; // So i can view address of x
std::cout << "x Before is equal "<< x <<std::endl;
int y ;
std:: cin >> std::hex >>y;
int *pinter = (int*)y ;
*pinter = 20;
std::cout << "x After is equal "<< x <<std::endl;
}

这段代码应该绕过 c++ 编译器将 x 变量类型设置为const int的概念,这样既不会指向变量的指针(不像在 C 中指向常量的指针可以更改常量的值(和对变量的引用都可以更改变量,因此此代码应该获取变量 x 的地址(当然在打印出来之后(,然后指针执行其余部分工作,所以我在这里搞砸了,因为它的接缝就像这个内存位置受到硬件保护(我知道不是,但我很困惑(

这段代码应该绕过 c++ 编译器将 x 变量类型设置为 const int 的概念,以便 [...]

你可以打破语言的规则,但你的代码C++无效。您不得修改符合const条件的内容。如果你这样做,你就有未定义的行为。由于编译器是为了编译有效的C++,因此他们不被强制对无效代码做任何有意义的事情,结果可以是任何东西,也可以是没有。

正如评论中已经说过的:

const与硬件或内存无关。这是你和你的编译器之间的协议,你违反了该协议。作为奖励,编译器会对您的代码执行任何操作,但不一定是您所期望的。

您试图通过在运行时进行修改来欺骗编译器,以便在编译时编译器无法知道您将修改const。但是,您确实将x声明为const因此编译器将假定其值不会更改。如果您仍然修改x的值,则可能发生任何事情。

PS:人们经常想出一些技巧来"证明"private并不是真正的隐私,cosnt并不是真正的const和相似。问题是:这些工具应该可以帮助您减少错误并编写更干净的代码。如果您努力尝试这些设施,您将设法做到这一点(有时甚至不调用 UB(。然而,这"证明"除了有可能搬起石头砸自己的脚之外,什么也"证明"。C++不是Java,它不会牵着你的手,并试图阻止你犯每一个可能的错误。在这方面,C++更接近于蟒蛇,"我们都是这里的成年人"。

const 提供给: 1. 注释不应更改的值 2. 允许编译器更好地优化代码,因为它不应该被更改。

你不必跳过所有这些箍,你可以用"const_cast"来改变恒常性。

编译器"帮助"您强制执行常量,但如您所展示的,有很多方法可以绕过它。如果要更改常量值将产生 UB。

不起作用的原因(除了 UB 和编译器可能会在知道xconst的情况下优化代码(可能是因为如果你在 64 位系统上运行int y无法保存x的地址。该地址很可能是设置了前 32 位之一的 64 位地址 - 您的int很可能是 32 位。

使用正确的类型来存储地址并进行xvolatile const,您仍然会有 UB - 但它可能只是按您的预期工作

#include <cstdint>
#include <iostream>
int main()
{
volatile const int x = 10;    
std::cout << "x Before is equal "<< x <<std::endl;
std::uintptr_t y = (std::uintptr_t) &x;
int *pinter = (int*) y;
*pinter = 20;
std::cout << "x After is equal "<< x <<std::endl;
}

最新更新