简体   繁体   English

为什么malloc()分配的内存比要求的多,并且如何在Mac OS X中禁用malloc?

[英]Why is malloc() allocating more memory than demanded and how can I disable malloc from doing this in Mac OS X?

I am making a program for a robot which stores a Maze as a Multi-Dimensional Dynamic Adjacency Array, and since the nodes will be discovered along the Maze Traversal, I am trying to allocate initial memory for it and then reallocate memory once a new node is found. 我正在为一个机器人程序编写一个程序,该程序将迷宫存储为多维动态邻接数组,并且由于将沿着迷宫遍历发现节点,因此我尝试为其分配初始内存,然后在重新分配新节点后重新分配内存被发现。 However, I once realized that I was storing more data than I had allocated using malloc (I had forgotten to use realloc ) and despite that it was not giving me some sort of a segmentation fault or some other error. 但是,我曾经意识到我存储的数据要比使用malloc分配的数据多(我忘记使用realloc ),尽管它没有给我带来某种分段错误或其他错误。 So I was interested to know: 所以我很想知道:

  1. Why does malloc allocate more memory than required? 为什么malloc分配的内存超出了要求?
  2. How can I disable this so that I can properly debug my program? 如何禁用此功能,以便可以正确调试程序? I am sure that the robot would not have loads of heap memory like my 16GB RAM MacBook so I would want to know if my program works within the memory I had allocated to it in the program. 我确定该机器人不会像我的16GB RAM MacBook那样拥有堆内存,因此我想知道我的程序是否在程序中分配给它的内存中工作。

Thank you for your response! 感谢您的答复!

Unlike what most people think, malloc does not allocate the memory directly from the kernel. 与大多数人的想法不同,malloc不会直接从内核分配内存。 Instead, it takes a chunk of memory from the kernel, and then manages that chunk in user space with a data structure. 取而代之的是,它从内核获取一块内存,然后使用数据结构在用户空间中管理该内存块。 That data structure used to be a heap, hence calling it "heap memory". 该数据结构曾经是一个堆,因此将其称为“堆内存”。

The practical upshot of the above is that the memory allocated using malloc does not have invalid memory around it. 上面的实际结果是,使用malloc分配的内存周围没有无效的内存。 Overstepping the memory by a little will not, in fact, cause your program to crash. 实际上,将内存稍微增加一点不会导致程序崩溃。

In addition to the above, malloc itself does not allocate in any size you wish. 除上述内容外,malloc本身不会以您希望的任何大小进行分配。 It usually allocates chunks in multiples of 8, 16 or 32 bytes, depending on the data structure used to manage the heap. 它通常以8、16或32字节的倍数分配块,具体取决于用于管理堆的数据结构。 When you allocate 1 byte with malloc, you are actually getting around 15 bytes that will never be used by anyone. 当您使用malloc分配1个字节时,实际上得到了大约15个字节,任何人都不会使用。 Overwriting those bytes will not cause any noticeable ill effect. 覆盖这些字节不会引起任何明显的不良影响。

If you want to make sure your program works with a small amount of memory, rlimit/ulimit and co are your friends. 如果要确保程序使用少量内存,rlimit / ulimit和co是您的朋友。 If you want to make sure you are not overstepping your allocated buffers, I strongly recommend the address sanitizer. 如果要确保不超出分配的缓冲区,我强烈建议使用地址清理器。 Compile (both clang and gcc) with -fsanitize=address , and your program will crash as soon as you overstep your buffers. 使用-fsanitize=address编译(clang和gcc),一旦您超出缓冲区,程序将崩溃。 This comes at a performance cost, of course. 当然,这是以性能为代价的。

I'll also add that hardware access control are only possible on page boundaries. 我还要补充说,仅在页面边界上才可以进行硬件访问控制。 On Intel, that's 4096 bytes. 在Intel上,为4096字节。 Even for memory allocated from the kernel, accesses past the end of the allocation will not trigger a segmentation fault if they do not step outside the allocated page. 即使对于从内核分配的内存,如果分配结束后的访问未移出分配的页面,它们也不会触发分段错误。

  1. It doesn't, you just got lucky. 不,您只是幸运。 Your program invoked undefined behavior, so anything could have happened. 您的程序调用了未定义的行为,因此任何事情都可能发生。

  2. If you want to run your program in a constrained environment, to simulate the fact that your target machine has limited memory, you can. 如果要在受限环境中运行程序,可以模拟目标计算机内存有限的事实。 Before launching your program, in your shell, run this command: ulimit -Sv 1000 . 在启动程序之前,请在外壳程序中运行以下命令: ulimit -Sv 1000 It's in kilobytes, so 1000 means 1 megabyte. 它以千字节为单位,因此1000表示1兆字节。

For more on ulimit, see here: http://ss64.com/osx/ulimit.html - you can use it on Linux too. 有关ulimit的更多信息,请参见此处: http : //ss64.com/osx/ulimit.html-您也可以在Linux上使用它。

You can also use the C function setrlimit() to do similar within your program, if you don't feel like running ulimit every time. 如果您不想每次都运行ulimit ,也可以使用C函数setrlimit()在程序中执行类似的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM