C++ 为什么新的double[26]有224个元素?

C++ 为什么新的double[26]有224个元素?,c++,arrays,pointers,C++,Arrays,Pointers,看起来是个非常愚蠢的问题: 以下是如何声明数组指针: double * y = new double[26]; 声明之后,我在程序运行时观看了y,下面是我所看到的: name value y[224] 8.691694942331e-310#DEN y[225] CXX0030: Error: Expression cannot be evaluated 所以我想知道为什么一个长度为26的双数组有224个元素?谢谢 编辑: 但是我试过这个密码,它成功了 int nPt = 26; do

看起来是个非常愚蠢的问题: 以下是如何声明数组指针:

double * y = new double[26];
声明之后,我在程序运行时观看了y,下面是我所看到的:

name    value
y[224] 8.691694942331e-310#DEN
y[225] CXX0030: Error: Expression cannot be evaluated
所以我想知道为什么一个长度为26的双数组有224个元素?谢谢

编辑: 但是我试过这个密码,它成功了

int nPt = 26;
double * y = new double[nPt];
y[224] = 0;

如果没有y[224],如何分配它的值呢?

您的数组只有26个元素,并且超出了它的界限。这是未定义的行为。程序不必崩溃,它只是意味着任何事情都有可能发生。这是一件坏事,必须避免

所以我想知道为什么一个长度为26的双数组有224个元素


没有。调试器似乎无法确定
y
只有26个元素

但是我试过这个密码,它成功了

int nPt = 26;
double * y = new double[nPt];
y[224] = 0;

该守则已生效。这并不意味着它必须崩溃;它可以随意以任何方式失败(或不失败)。

当您使用
new double[26]
分配内存时,系统将为您的应用程序提供一块至少可容纳26 x sizeof(double)的内存。分配函数确实会将数字26(或以其他方式将数字26取回来的东西)存储在其元数据中的某个位置,用于内存分配

但是,调试器将无法“计算”元素的数量是26,它只知道这是指向某些
值的指针。当你要求看起来超过26岁时,你处于“未定义的行为”状态——任何事情都可能发生。包括它完全按照您的“预期”显示(也就是说,内存是可读的,并且包含可以显示为“double”的值)。然后,当您到达元素224时,调试器无法再读取内存(因为操作系统已将其标记为“不可用”)。此时它停止。它可能已为50000000[在这种情况下,你可能又花了几个小时才来到这里问这个问题……]

好的。为了简单起见,假设我们有一台内存为100KB的计算机。处理器分配内存的方式是每次4KB的页面。因此我们有25个页面。其中一些页面是“堆”(其中
new
获取内存)。一个内存分配会得到这样一个4KB页面的一部分。假设我们的内存恰好位于第18-18*4096=73728到77823页。第19页标记为“未使用”。我们在这个页面中的分配是168字节(前168字节用于其他内容)-所以我们的地址是73896,现在,我们有26*8=208字节,所以“下一个可用字节”页面上的是73728+376=74104。因此,y[0]的地址是73896,我们每个人都会占用8个字节。当我们到达74104(索引26,我们分配的内存之外的一个)时,我们仍然在第18页,根据处理器/OS,它仍然“可供使用”。在处理器说“你不能去那里”之前,我们必须一直到77824.74104-77824=3720字节,或465*sizeof(double)。但我们正在使用被告知不要使用的内存。因此,在您的测试用例中,“剩余页面”的数量显然比我的示例中要少

我希望这能很好地解释这一点



它是4KB的原因是,如果处理器必须跟踪内存的每个字节,那么跟踪该字节是否可用将占用太多内存。4KB是“我们在外出足够长的时间后检测到”和“它占用太多容量”之间的一个很好的折衷.

数组在C/C++中不存在。事实上,像t[i]这样的表达式只是一个捷径(一个语法糖),表示我想访问地址t之外的第i个内存位置。当分配一个大小为N的新内存块时(new int[N]),系统提供了一个地址,从该地址可以安全地从返回的地址访问N个内存位置(注意,当我说N个内存位置时,它不是N个字节,而是N*sizeof_one_element_in_bytes)但是C/C++允许您计算从返回的地址派生的任何地址,这取决于您是否访问错误地址。C/C++运行时对数组大小一无所知,它无法保护您免受此类错误的影响。C/C++指针非常容易出错,您必须非常小心地使用它。这是接近t的代价机器和/或效率。y只有26个元素。那么为什么会有y[224]?它只是那个内存位置中发生的任何事情。@NickTsui:没有。没有什么可以阻止你索引数组末尾并获得未定义的行为。@NickTsui,未定义的行为。没有必要去思考它。在我的程序中,我要的是25以上的任何东西;但我很好奇,通过手动键入发现了这一点手表窗口中的e y[224]。很抱歉,我的意思是我的程序没有超过25。@NickTsui我第一次得到它:-)所以这与我使用的调试器有关?我使用的是vs2008。@NickTsui:没错。如果你要访问
y[224]
在代码中,您会得到未定义的行为。调试器是一个不同的故事,因为它在C++的边界之外运行:它只显示在
y+224
内存中发生的任何事情。好吧。我会接受这个答案。谢谢。等等,请参阅线程中的我的更新。@NickTsui:您添加到问题中的代码的行为它不必崩溃。很可能发生的是它覆盖了一些随机内存,但结果却不可预知。但是为什么每次都在224点停止?它看起来并不随机。@ NickTsui实现在C++规范的范围内可以自由地做任何它想做的事情;这并不意味着结果是随机的;如果你是RunNi的话。一次又一次地运行同一个程序你可能(但不能保证)会得到类似的结果,因为你每次都以同样的方式分配内存。多亏了你们大家,我认为你们所有的答案都是正确的,但是