为什么我在运行以下代码时没有收到错误

Why don't I get an error when I run the following code

本文关键字:错误 代码 运行 为什么      更新时间:2023-10-16

我正在运行以下代码,其中我声明了一个动态2D数组,然后在列索引处分配值,该列索引高于实际分配给动态数组的列数。然而,当我这样做的时候,代码运行得很完美,我没有得到错误,我相信我应该得到错误。

 void main(){

        unsigned char **bitarray = NULL;
        bitarray = new unsigned char*[96];
        for (int j = 0; j < 96; j++)
        {
                bitarray[j] = new unsigned char[56];
            if (bitarray[j] == NULL)
            {
                cout << "Memory could not be allocated for 2D Array.";
                return;// return if memory not allocated
            }
        }
        bitarray[0][64] = '1';
        bitarray[10][64] = '1';
        cout << bitarray[0][64] << " " << bitarray[10][64];
        getch();
        return;
    }

我得到的输出链接在这里(值实际上是准确分配的,但不知道为什么)。

在C++中,在缓冲区的边界之外访问缓冲区会调用未定义的行为(而不是您所期望的陷阱错误)。

C++规范将术语未定义行为定义为:

本国际标准没有要求的行为。

在您的代码中,两个

    bitarray[0][64] = '1';
    bitarray[10][64] = '1';

正在访问超出限制的内存,。即那些存储器位置是"无效的"。访问无效内存会调用未定义的行为。

访问违规错误或分段错误是UB的许多可能结果之一。没有什么是可以保证的。

从分段故障的wiki页面,

在使用硬件内存分段提供虚拟内存的系统上,当硬件检测到试图引用不存在的段或引用段边界之外的位置时,就会发生分段故障。。。。。

因此,可能,只是可能bitarray[0][64]的内存区域在分配的页面(段)内,在这种非常特殊的情况下,程序可以访问(但无论如何都无效)。这并不意味着它将永远如此。

也就是说,void main()不是main()函数的正确签名。main()的推荐签名(C++11,§3.6.1)为int main(void)

C++11引入了std::array和方法at()提供了越界检查。