猿问

我可以使用比使用malloc()分配的内存更多的内存,为什么?

我可以使用比使用malloc()分配的内存更多的内存,为什么?

char *cp = (char *) malloc(1);strcpy(cp, "123456789");puts(cp);

gcc(Linux)和Visual C ++ Express上的输出是“123456789”,这是否意味着当有空闲内存时,我实际上可以使用比我分配的更多malloc()

为什么malloc(0)不导致运行时错误?


白猪掌柜的
浏览 567回答 3
3回答

收到一只叮咚

您已经提出了一个非常好的问题,也许这会激起您对操作系统的兴趣。您已经知道自己已经设法通过此代码实现了一些您通常不希望做的事情。所以你永远不会在你想要便携的代码中这样做。更具体地说,这完全取决于您的操作系统和CPU架构,操作系统会为您的程序分配“页面”内存 - 通常这可能是4千字节的顺序。操作系统是页面的守护者,将立即终止尝试访问尚未分配的页面的任何程序。malloc另一方面,它不是操作系统功能,而是C库调用。它可以通过多种方式实现。您的调用很可能malloc导致来自操作系统的页面请求。然后我malloc会决定给你一个指向该页面内单个字节的指针。当您从给定位置写入内存时,您只是在操作系统授予您程序的“页面”中写入,因此操作系统不会看到任何错误操作。当然,当您继续调用malloc分配更多内存时,真正的问题就会开始。它最终将返回指向您刚刚写入的位置的指针。当您写入合法的内存位置(从操作系统的角度来看)时,这称为“缓冲区溢出”,但可能会覆盖程序的另一部分也将使用的内存。如果你继续学习这个主题,你将开始理解如何使用这种“缓冲区溢出”技术来利用程序 - 甚至可以开始将汇编语言指令直接写入将由另一个执行的内存区域。你的计划的一部分。当你到达这个阶段,你将获得很多智慧。但请遵守道德规范,不要用它来破坏宇宙!PS当我说上面的“操作系统”时,我的意思是“操作系统与特权CPU访问一起”。如果进程尝试使用尚未分配给该进程的页面,则CPU和MMU(内存管理单元)会触发特定的操作系统中断或回调。然后,操作系统会干净地关闭您的应用程序,并允许系统继续运行。在过去,在内存管理单元和特权CPU指令之前,您几乎可以随时在内存中的任何位置写入 - 然后您的系统将完全受到内存写入后果的支配!

绝地无双

不,你得到了不明确的行为。这意味着任何事情都可能发生,从它崩溃(yay)到它“工作”(boo),重新格式化你的硬盘并填充文本文件,说“UB,UB,UB ......”(wat)。想知道之后发生了什么是没有意义的,因为它取决于你的编译器,平台,环境,时间,最喜欢的汽水等等,所有这些都可以随心所欲地做任何他们想要的事情。更具体地说,使用未分配的任何内存是未定义的行为。你得到一个字节的malloc(1),仅此而已。

慕莱坞森

当您要求malloc1个字节时,它可能会从操作系统获得1页(通常为4KB)。此页面将分配给调用进程,因此只要您不离开页面边界,就不会有任何问题。但请注意,它绝对是未定义的行为!考虑以下(假设的)使用时可能发生的情况的示例malloc:malloc(1)如果malloc是内部的内存不足,它会问操作系统的更多一些。它通常会收到一个页面。假设它的大小为4KB,地址从0x1000开始您的呼叫返回,为您提供要使用的地址0x1000。由于您要求1个字节,因此如果您仅使用地址0x1000 ,则会定义行为。由于操作系统刚刚从地址0x1000开始为您的进程分配4KB内存,因此如果您从/向地址0x1000-0x1fff读取/写入内容,它将不会抱怨。所以你可以愉快地这样做,但它是未定义的行为。假设你做另一个 malloc(1)现在malloc仍然有一些内存,因此不需要向操作系统询问更多内存。它可能会返回地址0x1001。如果使用第一个字节给出的地址写入超过1个字节malloc,则在使用第二个地址时会遇到麻烦,malloc因为您将覆盖数据。所以问题是你一定通过malloc获得1个字节,但它可能是malloc内部已经给你处理更多的内存分配。
随时随地看视频慕课网APP
我要回答