在C ++中为数组分配特定内存量的目的是什么?

时间:2015-10-01 03:57:33

标签: c++ arrays pointers

我是一名学生在本学期参加C ++数据结构课程,我遇到了一些今晚我不太了解的事情。假设我要创建一个指向堆上数组的指针:

int* arrayPtr = new int [4];

我可以使用指针语法

访问此数组
int value = *(arrayPtr + index);

但是如果我在为数组分配的空间结束后立即向内存位置添加另一个值,那么我就可以访问它了

*(arrayPtr + 4) = 0;
int nextPos = *(arrayPtr + 4);
//the value of nextPos will be 0, or whatever value I previously filled that space with

*(arrayPtr + 4)的内存位置超过了为数组分配的空间的末尾。但据我了解,上述情况仍然不会造成任何问题。因此除了它是C ++的要求之外,为什么在声明它们时甚至给数组赋予特定的大小?

5 个答案:

答案 0 :(得分:6)

当你超过分配内存的末尾时,你实际上正在访问其他一些对象的内存(或者现在是免费的内存,但以后可能会改变)。因此,导致您出现问题。特别是如果你试图写点东西的话。

答案 1 :(得分:3)

  

我可以使用指针语法

访问此数组      

int value = *(arrayPtr + index);

是的,但不要。使用arrayPtr[index]

  

*(arrayPtr + 4)的内存位置超过了为数组分配的空间的末尾。但据我了解,上述情况仍然不会造成任何问题。

你理解错了。哦,非常错。您正在调用未定义的行为,并且未定义未定义的行为。它可能会工作一周,然后在下周休息一天,你会想知道为什么。如果您事先不知道集合大小,请使用动态内容,例如vector而不是数组。

答案 2 :(得分:3)

是的,在C / C ++中,您可以访问您声称已分配的空间之外的内存。有时。这就是所谓的未定义的行为

基本上,您已经告诉编译器和内存管理系统您希望空间存储四个整数,并且内存管理系统为您分配了存储四个整数的空间。它给了你一个指向那个空间的指针。在内存管理器的内部记帐中,ram的那些字节现在被占用,直到你调用delete[] arrayPtr;

但是,内存管理器还没有为您分配下一个字节。一般来说,你没有办法知道下一个字节是什么,或者它属于谁。

在一个简单的示例程序中,例如,只分配几个字节,并且不分配任何其他内容,可能是下一个字节属于您的程序,并且没有被占用。如果该阵列是程序中唯一动态分配的内存,那么可能是可能可以安全地运行到底。

但是在一个更复杂的程序中,有多个动态内存分配和解除分配,特别是在内存页边缘附近,你真的没有办法知道你要求包含的内存之外的任何字节。因此,当您在new中写入您要求的内存之外的字节时,您可以写入基本上任何内容。

这是未定义的行为的用武之地。因为你不知道你写的那个空间里有什么,你不知道会发生什么。结果。以下是可能发生的事情的一些例子:

  • 写入内存时未分配内存。在那种情况下,数据很好,似乎没有任何不好的事情发生。但是,如果稍后的内存分配使用该空间,那么您尝试放置的任何内容都将丢失。

  • 写入内存时已分配内存。在这种情况下,恭喜你,你刚刚从你程序中其他地方的某些其他数据结构中覆盖了一些随机字节。想象一下,用随机数据替换一个对象中的某个变量,并考虑这对您的程序意味着什么。也许其他地方的列表现在有错误的计数。也许字符串现在有前几个字符的随机值,或者现在为空,因为你用零替换了这些字符。

  • 数组是在页面边缘分配的,因此下一个字节不属于您的程序。该地址不在您的计划分配范围内。在这种情况下,操作系统会检测到您访问不属于您的随机内存,并使用SIGSEGV立即终止您的程序。

基本上,未定义的行为意味着您正在做违法的事情,但由于C / C ++的设计速度很快,语言设计师不会进行明确的检查以确保您不会像其他语言一样打破规则(例如Java,C#)。他们只是将违反规则的行为列为未定义,然后制作编译器的人可以使输出更简单,更快的代码,因为没有进行数组边界检查,如果你违反了规则,它就是你自己的问题。

所以是的,这有时会奏效,但不要依赖它。

答案 3 :(得分:0)

在纯粹的抽象设置中不会出现任何问题,您只需要担心算法的逻辑是否合理。在这种情况下,根本没有理由声明数组的大小。但是,您的计算机存在于物理世界中,并且只有有限的内存量。当你分配内存时,你要求操作系统让你使用一些计算机的有限内存。如果超出此范围,操作系统阻止您,通常是通过终止您的进程/程序。

答案 4 :(得分:-2)

是的,您必须将其写为arrayptr [index],因为*(arrayptr + 4)内存中的位置超过了为数组分配的空间的末尾。它是C ++中的一个缺陷,即一旦分配,数组大小就无法扩展。