使用未分配的内存没有错误?

sil*_*eth 8 c++ linux windows memory-management

为什么这样做?

#include <iostream>
using namespace std;

int main() {
    float* tab[3];

    int i = 0;
    while(i < 3) {
        tab[i] = new float[3-i];
        i++;
    }

    cout << tab[2][7] << endl;
    tab[2][7] = 6.87;
    cout << tab[2][7] << endl;

    i = 0;
    while(i < 3)
        delete[] tab[i];
}
Run Code Online (Sandbox Code Playgroud)

虽然这个没有?

#include <iostream>
using namespace std;

int main() {
    float* tab = new float[3];

    cout << tab[7] << endl;
    tab[7] = 6.87;
    cout << tab[7] << endl;

    delete[] tab;
}
Run Code Online (Sandbox Code Playgroud)

我在Win XP上使用MS VS 2008尝试了两个程序,两个程序都编译没有错误,第一个程序运行没有任何错误.第二个弹出一些错误窗口,但是我记不住它了,无法重现(目前无法访问Windows).

我也尝试使用g ++在Linux(带有预编译内核包版本2.6.35.23.25的Kubuntu 10.10)上进行编译和运行,没有任何错误.

为什么?不应该有任何弹出窗口,例如"错误访问未分配的内存"?

我知道它应该(并且,幸运的是)编译没有错误,但我认为它不应该没有它们运行...为什么第二个例子在Windows上而不是在Linux上发生错误?

Ste*_*end 9

使用未分配的内存会导致未定义的行为.即使在相同的系统和编译器上执行此操作,您也不会期望会发生什么,更不用说跨硬件和编译器的不同组合了.

程序可能会立即崩溃,它可能会工作一段时间然后再失败,它甚至可能看起来完美无缺.

但是,访问您不拥有的内存始终是一个编程错误.不要把正确操作的外观想象为"它有时会起作用",把它想象成"我真的很不走运,我的虫子很快就不会出现".


Edw*_*nge 7

虽然除了马克之外的其他答案没有错,但他们也不完全正确.通过在程序中明确分配的内容之后访问数据,您正在做的是导致"未定义的行为".它可以做任何事情,包括"工作".

当我开始写这篇文章时,史蒂夫的回答并不存在.

  • +1并发发布也导致未定义的行为,fyi (2认同)

Ebo*_*ike 5

它们都进行了越界数组访问 - 你有一个包含3个浮点指针的数组,你正在访问第8个数组.这肯定会崩溃.

但是,与Java或其他一些托管语言不同,每个阵列访问都没有明确的边界检查(因为它的性能成本太高).所以检查你的唯一界限是你的MMU.如果您最终访问不属于您的应用程序的内存,您将崩溃.如果你点击了未分配的内存,但仍然恰好是你的过程的一部分(例如,可能是一个保护词),它将默默地成功.对于非常难以追踪的错误,这是一个很好的秘诀.

界限检查是关键.尽可能做到.