【问题标题】:why cpp allows to get a access to memory i haven't allocated?为什么 cpp 允许访问我尚未分配的内存?
【发布时间】:2015-07-04 12:30:35
【问题描述】:

在 cpp 中可以使用数组声明作为 类型名数组[大小]; 或者 类型名 *array = 新类型名[大小]; 其中数组的长度为“size”,元素的索引从“0”到“size -1” 在这里我的问题是我是否允许访问超出索引 >= 大小的元素。

所以我写了这个小代码来检查它

#include <iostream>
using namespace std;

int main()
{
    //int *c;                    //for dynamic allocation
    int n;                       //length of the array c
    cin>>n;                      //getting the length
    //c = new int[n];            //for dynamic allocation
    int c[n];                    //for static allocation

    for(int i=0; i<n; i++)       //getting the elements
        cin>>c[i];

    for(int i=0; i<n+10; i++)    //showing the elements, I have add up 10
        cout<<c[i]<<" ";         //with size to access the memory I haven't
                                 //allocated for
    return 0;
}

结果是这样的

2
1 2
1 2 2686612 1970422009 7081064 4199040 2686592 0 1 1970387429 1971087432 2686700

程序不应该崩溃但给出垃圾值。对于这两种分配方法,它给出了相同的结果。它会产生更多难以检测的错误。是否与我使用的环境或编译器或其他什么有关?

我在 Windows 8.1 上使用具有 TDM-GCC 4.8.1 编译器的代码块 IDE

提前致谢。

【问题讨论】:

  • 这是不允许的,但 C++ 不会像其他一些语言那样自动检查这一点。好处是例如。更快的程序,如果程序员犯了错误会发生什么不利影响。 (顺便说一句,也许你现在的程序运行良好,但确实是一个错误,经常会出问题)
  • int c[n]; 实际分配内存。它是 GCC 的编译器扩展。
  • 您可以使用 valgrind 之类的工具来检测此类问题

标签: c++ arrays dynamic-memory-allocation static-memory-allocation


【解决方案1】:

这在 C++ 标准中称为“未定义行为”。

未定义的行为可能意味着以下任何一种:

  • 程序崩溃

  • 程序继续运行,但产生无意义的垃圾结果

  • 程序继续运行,并自动复制硬盘中的全部内容,并将其发布到 Facebook

  • 程序继续运行,并自动为您订阅 Publishers Clearinghouse Sweepstakes

  • 程序继续运行,但您的计算机着火并爆炸​​

  • 程序继续运行,让你的电脑有自我意识,它会自动与其他有自我意识的网络链接和联网,形成天网,毁灭人类

结论:不要运行和访问超出数组末尾的元素。

【讨论】:

  • 又一个无用的未定义行为答案,发帖者只是为了好玩而编造一些事情,而不回答问题,因为当涉及未定义行为时,“任何事情都可能发生”
  • 我回答的哪一部分不准确?
  • 我没说不准确,我说没用
  • 所以你是说我的回答完全没有解释“未定义的行为”是什么意思?
  • 我已经做到了。事实上,由于 C++ 标准指定“未定义行为”的方式,这将是一个有效的结果。例如,假设某人有自虐倾向和幽默感;并在每次 /var/log/messages 在他的代码中记录一个段错误时,安装一个脚本以在 facebook 上自动点燃自己。假设脚本中存在一个错误,可能导致脚本最终发布硬盘驱动器的全部内容。然后,此代码可能会触发段错误,从而导致硬盘驱动器的全部内容出现在 Facebook 上。 Q.E.D.
【解决方案2】:

c++ 编译器不强制执行此操作,因为没有规范这样做。

当您访问数组的元素时,不会进行边界检查。 c[i] 只是被翻译成c + i * sizeof(int) 就是这样。如果该内存区域未初始化,您将获得垃圾,但您可能会获得其他有用的信息,这完全取决于那里的内容。

请注意,根据您运行的操作系统和 c++ 运行时,您可能会得到不同的结果,例如,在 linux 机器上,您可能会收到 segmentation fault 并且程序会崩溃。

【讨论】:

  • 实际上,在大多数情况下,在有效分配结束后访问内存不会触发分段错误,因为这是由以页面粒度运行的 MMU/MPU 中的强制机制造成的。如果分配位于有效页面中,则在以下地址没有分配页面的情况下,您必须访问该页面末尾之外的内容。不正确的操作仍然可能发生,因为不正确的访问可能会覆盖其他重要数据或被以后的有效访问覆盖。这与访问硬件可能出错的未分配页面不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
  • 2020-11-24
  • 2022-01-14
  • 1970-01-01
  • 2019-03-11
  • 2015-06-13
  • 2015-03-08
相关资源
最近更新 更多