为什么分配内存?(C++)

Nit*_*arg 0 c++ memory arrays memory-leaks memory-management

我试图理解C++中的内存分配.我想到的一个问题是为什么分配内存是如此必要?如果我们在不分配内存的情况下使用内存会发生什么?另外,我很震惊地看到C++在内存分配方面是多么粗心.如果通过没有边界检查的数组提供对内存的自由访问.

int main()
{
int *p = new int[5];
p[1] = 3;
p[11118] = 9;
cout<<p[11118]<<'\n';
}
Run Code Online (Sandbox Code Playgroud)

上面的代码工作,输出9.

在什么情况下将值分配给未分配的内存位置会很危险?什么是潜在的不良影响?我正在访问的内存位置是否可能已分配给某个其他程序并为其分配值可能会导致该程序以非常意外的方式崩溃/表现?

Arm*_*yan 16

上面的代码是Undefined Behavior.它可以工作,工作不正常,根本无法工作,崩溃或通过Microsoft Skype订购披萨.你不应该依赖未定义的行为:)

  • @MK:幸运的你!我曾被迫为卡尔·马克思的整个作品付费,我的out_of_bounds索引是通过亚马逊订购的. (5认同)
  • @BlackBear:哦,是的,我认为确实如此.他问危险什么时候?这总是危险的 (4认同)
  • 披萨+ 1! (3认同)

Den*_*ose 11

为什么分配内存是必要的? 因此,您将内存标记为您的内存.没有其他人可以使用它.它还验证实际上有可用的内存.如果你的系统只有1000字节的内存,那么选择字节1500来存储一些数据是一个坏主意.

如果我们使用内存而不分配它会发生什么? 没人知道.您写的地址可能不存在.可能已经开始使用其他进程,因此您将覆盖其数据.记忆可以得到保护; 例如,在前一种情况下,操作系统可能会注意到您正在访问另一个进程声称的内存,并阻止您.您可能拥有该内存区域,但程序的另一部分由于某种原因正在使用它,并且您已经覆盖了自己的数据.

通过没有边界检查的数组自由访问内存. 那段代码不起作用......它现在正如预期的那样运作,但这不是一回事.形式上,这是未定义的行为,因此编译器可以发出代码来执行它想要的任何操作.

在什么情况下将值分配给未分配的内存位置会很危险? 我在上面给出了一些例子.也可以打破你的堆栈.调用函数时,将存储函数应返回的地址.如果你通过粗心的内存访问覆盖了这个值,那么当你离开那个函数时,谁知道你最终会在哪里?也许利用你的程序的人......一个常见的漏洞就是将可执行代码加载到内存的某个部分,然后使用现有程序中的错误来运行它.有一次,在我正在处理的嵌入式设备上,我遇到了fencepost错误导致我的函数返回到其他地方的另一个指令的中间.这应该会让我的芯片崩溃,但幸运的是,该指令的后半部分本身就是一个有效的指令.最终运行的代码序列导致设备获得了感知,并最终完成了我们自己正在处理的项目.现在,它只是在我的地下室玩魔兽.因此是未定义行为的恐怖.


Ker*_* SB 8

很多好的答案,但我觉得关于“为什么我们需要分配内存”缺少一些东西。我认为了解计算机程序的控制流在最低级别如何工作非常重要,因为 C 和 C++ 是硬件上相对较薄的抽象层。

虽然可以仅使用 ifs 和 goto 在一个巨大的全局范围内编写一个程序,但大多数现实世界的程序都被分成函数,这些函数是独立的、可移动的模块,可以随意相互调用。为了跟踪所有数据(参数、返回值、局部变量),所有这些数据都放在称为堆栈的一维连续内存区域。调用函数将内容放入堆栈中,从函数返回时会将数据弹出,并且相同的内存区域将被下一个函数调用覆盖。

这样,所有函数代码都可以通过仅记住本地数据相对于其入口点的偏移量来抽象存储,并且可以从许多不同的上下文调用相同的函数 - 函数的局部变量可能位于不同的绝对地址,但它们' re 始终位于相对于函数入口地址的相同相对位置。

事实上,当函数被调用和返回时,堆栈内存不断被覆盖,这意味着您不能将任何持久数据放置在堆栈上,即局部变量中,因为函数返回后,局部变量的内存不会保持完整。如果您的函数需要在某个地方存储持久数据,它必须将该数据存储在其他地方。这个另一个位置就是所谓的,您可以在其中手动(也称为“动态”)通过malloc或请求持久存储new。该内存区域位于其他地方,不会被任何人回收或覆盖,并且您可以根据需要安全地传递指向该内存的指针。唯一的缺点是,除非您手动告诉系统您已完成,否则它将无法将内存用于其他用途,这就是为什么您必须手动清理此动态分配的内存。但是函数需要存储持久信息是我们需要分配内存的原因。

(只是为了完成图片:堆栈上的局部变量据说是“自动分配”的。还有“静态分配”,它发生在编译时,是全局变量所在的位置。如果你有一个 global ,你可能会很char[30000]高兴从程序中的任何位置读取和写入。)


And*_*mas 6

在堆上分配内存允许动态分配具有动态生存期的动态内存量.

如果你想要边界检查,你可以通过std :: vector :: at()得到它.

在什么情况下将值分配给未分配的内存位置会很危险?

所有情况.

什么是潜在的不良影响?

意外的行为.

我正在访问的内存位置是否可能已分配给某个其他程序并为其分配值可能会导致该程序以非常意外的方式崩溃/表现?

取决于操作系统.