malloc()和堆内存

atv*_*atv 5 c memory

我在以下C代码中得到一个奇怪的结果.

int main()
{
    int *p = (int *) malloc(100);
    p[120] = 5;
    printf("\n %d", p[120]);
}
Run Code Online (Sandbox Code Playgroud)

由于我只分配了100个字节,因此该代码应该导致分段错误.但是,它打印'5'并且不会给出任何运行时错误.有人可以解释原因吗?

Hea*_*utt 20

不,代码不应该(必然)给出段错误.当您尝试访问未分配给您的进程的虚拟内存页时,会发生段错误.

"堆"或"免费存储"是您的进程拥有的虚拟内存页面区域.该malloc()API子划分该区域成块,并且将指针返回到该块.

如果超出了具有指针的块的末尾,则通常会访问作为堆的一部分的内存,但不会访问已分配块的内存.通过这种方式,您可以破坏其他堆块甚至malloc()用于定义堆的数据结构.

有关堆损坏的更多信息,以及在代码的调试版本中检测它的方法,这是一本很棒的书:

编写固体代码:微软的Steve Maguire开发无错误C程序的技术 替代文字

迂腐的附录:在极少数情况下,通过访问堆块末尾之外的内存,您可以访问不属于堆的内存.在这些情况下,您可能会遇到预期的分段错误.您还可能损坏堆之外的其他一些数据结构.这真是一个偶然的问题.但是,与典型的堆块相比,堆本身非常大,因此99%的时间代码(例如您的示例)将损坏堆.您提供的示例属于99%的情况.

  • TED这只是"有点"的真实.毫无疑问,他使用的是具有虚拟内存页面大小的计算机.据推测,可执行代码具有与堆不同的VM保护.我打赌他是在这样一个系统,因为C标准库malloc()函数存在.你写的是真的,特别是在Z-80上运行TRS-DOS的Radio Shack Model III上.;) (2认同)

Joh*_*kin 6

无效的内存访问不会总是导致分段错误,总线错误或其他崩溃.例如,如果你的阵列之后分配另一个块,你改变的值块-这可能是任何东西.