【问题标题】:Strange behavior when trying hacking a constant in C++ [duplicate]尝试破解 C++ 中的常量时的奇怪行为 [重复]
【发布时间】:2012-05-29 10:44:02
【问题描述】:

可能重复:
Modifying a const through a non-const pointer

我正在学习 C++,对指针非常感兴趣。我试图改变一个常量的值(我的老师叫它backdoor,如果我错了,请澄清)像这样:

const int i = 0;

const int* pi = &i;

int hackingAddress = (int)pi;
int *hackingPointer = (int*)pi;

*hackingPointer = 1;

cout << "Address:\t" << &i << "\t" << hackingPointer << endl;
cout << "Value:  \t" << i << "\t\t" << *hackingPointer << endl;

system("PAUSE");

return 0;

但是,结果很奇怪。两个地址虽然相同,但值不同。

我的代码是如何执行的? 0 和 1 的值究竟存储在哪里?

【问题讨论】:

  • 另外,从今天早些时候开始:stackoverflow.com/questions/10792757/…
  • @Mankarse 哇,也许那是我的朋友。我们之前讨论过这个问题,我不知道他在我之前发过 StackOverflow :) 我应该投票删除吗?

标签: c++ memory pointers


【解决方案1】:

您发现了一个被 C++ 开发人员称为未定义行为的小东西。您告诉编译器“i 是一个值为 0 的常量”。所以当你向编译器询问i 的值时,它会告诉你它是0。

试图改变常量的值违反了编译器所做的假设(常量将是,嗯,constant),因此,编译器将生成无效或不一致的代码。

在 C++ 中有很多情况可以在编译器不将其捕获为错误的情况下执行某些操作,但结果是 undefined。如果你这样做,那么你会得到你所看到的结果。编译器做了一些奇怪和意想不到的事情。

哦,如果你的老师试图通过这样的例子教你任何东西,他就错了,你应该很害怕。

唯一保证您可以从这样的代码中获得:

编译器可以做任何它喜欢的事情

当你编写代码时,你与编译器有一个隐含的契约:

“如果我编写了定义良好的 C++ 代码,那么您将其转换为可执行文件,其效果与 C++ 标准所描述的相同”。

当你做这样的事情时,你就违反了合同。然后编译器也没有义务遵循它。如果您提供的编译器代码没有按照 C++ 标准明确定义,那么它就不能也不会创建一个按照 C++ 标准指定的可执行文件。

【讨论】:

  • 感谢您的解释。我的老师没有教这个,我觉得这很有趣,我自己尝试了一下,当我问他这个结果时,他也无法解释为什么。无论如何,我有一个有趣的经历,谢谢你的清晰解释:)
【解决方案2】:

看来,编译器已经优化(inlined int const value)

cout << "Value:  \t" << i << "\t\t" << *hackingPointer << endl;

到

cout << "Value:  \t" << 0 << "\t\t" << *(0x0044ff28) << endl;

无论如何,您仍然成功地更改了存储i 的内存值。但是不要在家里尝试这个:-)

【讨论】:

    【解决方案3】:

    不允许更改常量的值,实际上这是未定义的行为,因此您的程序可以执行任何操作。

    在这种情况下,您的编译器似乎在编译时优化了读取,因为它知道值是固定的。许多实现可能会在您尝试更改它时崩溃,但您不能并且不应该赌注或依赖任何未定义行为的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      相关资源
      最近更新 更多