定制malloc用于许多小型固定大小的块?

时间:2021-03-13 03:48:46

I need to allocate, and free lots of fixed size, small (16 byte) blocks of memory, in no fixed order. I could just call malloc and free for each, but that will probably be very inefficient. A better solution probably would be to call malloc and free for larger blocks, and handle the allocation within those blocks itself.

我需要分配,并释放大量固定大小的小(16字节)内存块,没有固定的顺序。我可以为每个调用malloc和free,但这可能效率很低。一个更好的解决方案可能是调用malloc并释放更大的块,并处理这些块本身的分配。

The question is, how best to do this?

问题是,如何最好地做到这一点?

It seems that this should not be a very unusual problem or rare problem, and that it should have been "solved", but I can't seem to find anything. Any pointers?

这似乎不应该是一个非常不寻常的问题或罕见的问题,它应该已经“解决”,但我似乎找不到任何东西。有什么指针吗?

To clarify, I am aware that memory pool libraries, and what-not exist, but these also take a size parameter. If the size is constant, then different options for more efficient algorithms are available, are there any implementations of these?

为了澄清,我知道内存池库,什么不存在,但这些也需要一个大小参数。如果大小是恒定的,那么可以使用更高效算法的不同选项,这些是否有任何实现?

9 个解决方案

#1


5  

You're right, it's a common problem [Edit: how to do fixed-size allocation, I mean. "malloc is slowing down my application" is less common than you might think].

你是对的,这是一个常见的问题[编辑:如何进行固定大小的分配,我的意思是。 “malloc正在减慢我的应用程序”并不像你想象的那么常见]。

If your code is too slow and malloc a plausible culprit, then a simple cell allocator (or "memory pool") might improve things. You can almost certainly find one somewhere, or it's easy to write:

如果你的代码太慢而且malloc是一个看似合理的罪魁祸首,那么一个简单的单元分配器(或“内存池”)可能会改进。几乎可以肯定在某个地方找到一个,或者写起来很容易:

Allocate a large block, and put a singly-linked list node at the start of each 16-byte cell. Link them all together. To allocate, take the head off the list and return it. To free, add the cell to the head of the list. Of course if you try to allocate and the list is empty, then you have to allocate a new large block, divide it into cells, and add them all to the free list.

分配一个大块,并在每个16字节单元的开头放置一个单链接列表节点。把它们连在一起。要分配,请从列表中删除并返回它。要释放,请将单元格添加到列表的开头。当然,如果你尝试分配并且列表为空,那么你必须分配一个新的大块,将它分成单元格,并将它们全部添加到空闲列表中。

You can avoid that big up-front work if you want. When you allocate a big block, just store a pointer to the end of it. To allocate, move your pointer back 16 bytes through the block and return the new value. Unless it was already at the start of the block[*], of course. If that happens, and the free list is also empty, you need a new large block. Free doesn't change - just add the node to the free list.

如果你愿意,你可以避免那么大的前期工作。分配大块时,只需存储指向它结尾的指针。要分配,请将指针移回块中的16个字节并返回新值。当然,除非它已经在块[*]的开头。如果发生这种情况,并且空闲列表也是空的,则需要一个新的大块。 Free不会更改 - 只需将节点添加到空闲列表即可。

You have an option whether to deal out of the block first, and check the free list if that's exhausted, or to check the free list first, and deal off the block if that's empty. I don't know which tends to be faster - the good thing about a last-in-first-out free list is that it's cache-friendly, since you're using memory that was used recently, so I'd probably try that first.

您可以选择是先退出该块,还是先检查空闲列表(如果已用尽),或先检查空闲列表,如果空白,则处理该块。我不知道哪个往往更快 - 关于自上而下的免费列表的好处是它是缓存友好的,因为你使用的是最近使用的内存,所以我可能会尝试第一。

Note that the list node is not needed while the cell is allocated, so there's essentially zero overhead per cell. Quite aside from speed, this is likely to be an advantage over malloc, or other general-purpose allocators.

请注意,在分配单元时不需要列表节点,因此每个单元的开销基本上为零。除了速度之外,这可能比malloc或其他通用分配器更具优势。

Do be aware that dropping the whole allocator is pretty much the only way to release memory back to the system, so users who are planning to allocate a lot of cells, use them, and free them all, should create their own allocator, use it, and then destroy it. Both for performance (you don't have to free all the cells) and to prevent the fragmentation-style effect where a whole block must be kept if any of its cells are in use. If you can't do this, your memory use will be the high-water-mark of the time your program has been running. For some programs that's a problem (for instance a long-running program with occasional big spikes in memory use, on a system where memory is constrained). For others it's absolutely fine (for instance if the number of cells in use increases until very near the end of the program, or fluctuates within a range where you really don't care that you're using more memory than you strictly could). For some its actively desirable (if you know how much memory you're going to use, you can allocate it all up-front and not have to worry about failures). For that matter, some implementations of malloc have difficulty releasing memory back from the process to the OS.

请注意,丢弃整个分配器几乎是将内存释放回系统的唯一方法,因此计划分配大量单元,使用它们并释放所有单元的用户应该创建自己的分配器,使用它,然后摧毁它。两者都是为了性能(您不必释放所有单元格)并防止碎片式效果,如果任何单元格正在使用中,必须保留整个块。如果你不能这样做,你的记忆使用将是你的程序运行时间的最高标记。对于某些有问题的程序(例如长时间运行的程序,内存使用偶尔会出现大量峰值,在内存受限的系统上)。对于其他人来说,它绝对没问题(例如,如果使用的细胞数量增加,直到非常接近程序结束,或者在你真正不关心你使用的内存超出你的严格要求的范围内波动)。对于一些它的主动需求(如果你知道你将要使用多少内存,你可以预先分配它,而不必担心失败)。就此而言,malloc的某些实现难以将内存从进程释放回OS。

[*] Where "start of the the block" probably means "the start of the block, plus the size of some node used to maintain a list of all blocks, so they can all be freed when the cell allocator is destroyed".

[*]其中“块的开始”可能意味着“块的开始,加上用于维护所有块列表的某个节点的大小,因此当单元分配器被销毁时它们都可以被释放”。

#2


4  

Before embarking on the onerous task of re-writing malloc, the standard advice applies. Profile your code, and make sure that this is actually a problem!

在开始重写malloc的繁重任务之前,标准建议适用。描述您的代码,并确保这实际上是一个问题!

#3


4  

The best way to do this is to not assume it will be inefficient. Instead try out the solution with malloc, measure the performance and prove that it is either efficient or not. Then once it's provide to be innefficient (likely won't be) is the only time you should move to a custom allocator. Without the proof you'll never know if your solution is actually faster or not.

这样做的最好方法是不要假设它效率低下。而是尝试使用malloc解决方案,测量性能并证明它有效或无效。然后,一旦它提供的效率不高(可能不会)是唯一一次你应该转移到自定义分配器。没有证据,你永远不会知道你的解决方案是否真的更快。

#4


3  

for your requirement your custom allocator would be really simple. just calloc a large array memory

根据您的要求,您的自定义分配器非常简单。只是calloc一个大型数组内存

calloc(N * 16)

and then you can just hand out array entries. inorder to track which array locations are in use you could use a simple bitmap and then with a few clever bit operations and pointer subtraction your custom malloc/free operations should be pretty easy. if you run out of space you can just realloc some more, but having a suitable fixed default would be a little easier.

然后你可以分发数组条目。为了跟踪正在使用的数组位置,您可以使用一个简单的位图,然后使用一些聪明的位操作和指针减法,您的自定义malloc / free操作应该非常简单。如果你的空间不足你可以再重新分配一些,但是有一个合适的固定默认值会更容易一些。

though really you should just use malloc first. malloc creates pools of free memory blocks of different sizes, i would bet that there is a pool for 16 byte memory blocks (different implementations may or may not do this but its a pretty common optimization) and since all your allocations are the same size fragmentation should not be an issue. (plus debugging your allocator might be a bit of a nightmare.)

虽然你真的应该先使用malloc。 malloc创建了不同大小的可用内存块池,我敢打赌,有一个16字节内存块的池(不同的实现可能会或可能不会这样做,但它是一个非常常见的优化),因为所有的分配都是相同大小的碎片应该不是问题。 (加上调试你的分配器可能有点噩梦。)

#5


2  

What you're looking for is called a memory pool. There are existing implementations, although it's not hard (and good practice) to make your own.

您正在寻找的是一个内存池。有现成的实现,虽然创建自己的实现并不困难(和良好实践)。

The simplest implementation for a pool of same-sized data is just a wrapper containing a buffer of n*size, and a stack of n pointers. "malloc" from the pool pops the pointer off the top. "free" to the pool puts the pointer back into the stack.

对于相同大小的数据池,最简单的实现只是一个包含n *大小的缓冲区和一堆n个指针的包装器。池中的“malloc”将指针从顶部弹出。 “free”到池中会将指针放回堆栈中。

#6


1  

You could try overriding malloc/free with an alternative implementation that's suited to lots of small allocations.

您可以尝试使用适合大量小分配的替代实现来覆盖malloc / free。

#7


1  

Due to academic interest I was working on a solution to that problem a few days ago. The implementation is very simple but complete and you mentioned that you are looking for a drop-in replacement, so I think my implementation could work for you.

由于学术兴趣,我几天前正致力于解决这个问题。实现非常简单但完整,你提到你正在寻找替代品,所以我认为我的实现可能对你有用。

Basically it works like patros described, except that it automatically requests more memory if there are no free blocks any more. The code was tested with a large linked list (about 6 millon nodes, each 16 bytes in sizes) against a naive malloc()/free() scheme and performed roughly 15% faster than that. So supposedly it is usable for your intention. It is easy to adjust it to different block-sizes, since the block size specified when creating such a large chunk of memory.

基本上它就像描述的patros一样,只是如果没有空闲块就会自动请求更多的内存。该代码使用大型链表(大约6个节点,每个大小为16个字节)与一个天真的malloc()/ free()方案进行测试,并且执行速度比此快大约15%。所以据说它可以用于你的意图。由于在创建如此大的内存块时指定的块大小,因此很容易将其调整为不同的块大小。

The code is available on github: challoc

代码可以在github:challoc上找到

Example usage:

int main(int argc, char** argv) {
    struct node {
           int data;
       struct node *next, *prev;
    };
    // reserve memory for a large number of nodes
    // at the moment that's three calls to malloc()
    ChunkAllocator*  nodes = chcreate(1024 * 1024, sizeof(struct node));

    // get some nodes from the buffer
    struct node* head = challoc(nodes);
    head->data = 1;
    struct node* cur = NULL;
    int i;
    // this loop will be fast, since no additional
    // calls to malloc are necessary
    for (i = 1; i < 1024 * 1024; i++) {
            cur = challoc(nodes);
        cur->data = i;
        cur = cur->next;
    }

    // the next call to challoc(nodes) will
    // create a new buffer to hold double
    // the amount of `nodes' currently holds

    // do something with a few nodes here

    // put a single node back into the buffer
    chfree(nodes,head);

    // mark the complete buffer as `empty'
    // this also affects any additional
    // buffers that have been created implicitly
    chclear(nodes);

    // give all memory back to the OS
    chdestroy(nodes);

    return 0;
}

#8


0  

Wilson, Johnstone, Neely, and Boles wrote a nice paper surveying all sorts of different allocators.

Wilson,Johnstone,Neely和Boles写了一篇很好的论文,调查各种不同的分配器。

In my experience, the performance and overhead difference between a good fixed pool allocator and just relying on dlmalloc can be massive in cases where you're making lots and lots of short-lived small allocations in a limited address space (such as a system with no page file). In the app I'm working on at this moment, our main loop jumps from 30ms to >100ms if I replace our block allocator with simple calls to malloc() (and it eventually crashes due to fragmentation).

根据我的经验,一个好的固定池分配器和仅仅依赖于dlmalloc之间的性能和开销差异可能是巨大的,如果你在有限的地址空间(例如一个系统)中进行大量的短期小分配没有页面文件)。在我正在研究的应用程序中,如果我用简单的malloc()调用替换我们的块分配器,我们的主循环从30ms跳到> 100ms(并且它最终因碎片而崩溃)。

#9


0  

The following code is pretty ugly, but the purpose is not the beauty but to find out how big is the block allocated by malloc.
I asked for 4 bytes, and malloc requested and received 135160 bytes from OS.

下面的代码非常难看,但目的不是美观,而是要找出malloc分配的块有多大。我要求4个字节,并且malloc请求并从OS接收135160个字节。

#include <stdio.h>
#include <malloc.h>


int main()
{
  int* mem = (int*) malloc( sizeof(int) ) ;
  if(mem == 0) return 1;
  long i=1L;

  while(i)
    {
      mem[i-1] = i;
      printf("block is %d bytes\n", sizeof(int) * i++);
    }//while

  free(mem);
  return 0 ;
}

$ g++ -o file file.cpp
$ ./file
...
block is 135144 bytes
block is 135148 bytes
block is 135152 bytes
block is 135156 bytes
block is 135160 bytes
Segmentation fault

$ g ++ -o file file.cpp $ ./file ...块是135144字节块是135148字节块是135152字节块是135156字节块是135160字节分段错误

This malloc is serious business.
realloc doesn't do any system call if the requested size is less than it has available due to internal pooling.
After realloc copied the memory to a larger zone, it does nor destroy the previous block, not return it to system immediately. This can be still accessed (of course totally unsafe). With all these, it doesn't make sense to me, someone would need an additional memory pool.

这个malloc是严肃的事。如果请求的大小小于由于内部池而可用的大小,则realloc不会执行任何系统调用。在realloc将内存复制到更大的区域后,它也会破坏前一个块,不会立即将其返回给系统。这仍然可以访问(当然完全不安全)。有了这些,对我来说没有意义,有人需要一个额外的内存池。

#1


5  

You're right, it's a common problem [Edit: how to do fixed-size allocation, I mean. "malloc is slowing down my application" is less common than you might think].

你是对的,这是一个常见的问题[编辑:如何进行固定大小的分配,我的意思是。 “malloc正在减慢我的应用程序”并不像你想象的那么常见]。

If your code is too slow and malloc a plausible culprit, then a simple cell allocator (or "memory pool") might improve things. You can almost certainly find one somewhere, or it's easy to write:

如果你的代码太慢而且malloc是一个看似合理的罪魁祸首,那么一个简单的单元分配器(或“内存池”)可能会改进。几乎可以肯定在某个地方找到一个,或者写起来很容易:

Allocate a large block, and put a singly-linked list node at the start of each 16-byte cell. Link them all together. To allocate, take the head off the list and return it. To free, add the cell to the head of the list. Of course if you try to allocate and the list is empty, then you have to allocate a new large block, divide it into cells, and add them all to the free list.

分配一个大块,并在每个16字节单元的开头放置一个单链接列表节点。把它们连在一起。要分配,请从列表中删除并返回它。要释放,请将单元格添加到列表的开头。当然,如果你尝试分配并且列表为空,那么你必须分配一个新的大块,将它分成单元格,并将它们全部添加到空闲列表中。

You can avoid that big up-front work if you want. When you allocate a big block, just store a pointer to the end of it. To allocate, move your pointer back 16 bytes through the block and return the new value. Unless it was already at the start of the block[*], of course. If that happens, and the free list is also empty, you need a new large block. Free doesn't change - just add the node to the free list.

如果你愿意,你可以避免那么大的前期工作。分配大块时,只需存储指向它结尾的指针。要分配,请将指针移回块中的16个字节并返回新值。当然,除非它已经在块[*]的开头。如果发生这种情况,并且空闲列表也是空的,则需要一个新的大块。 Free不会更改 - 只需将节点添加到空闲列表即可。

You have an option whether to deal out of the block first, and check the free list if that's exhausted, or to check the free list first, and deal off the block if that's empty. I don't know which tends to be faster - the good thing about a last-in-first-out free list is that it's cache-friendly, since you're using memory that was used recently, so I'd probably try that first.

您可以选择是先退出该块,还是先检查空闲列表(如果已用尽),或先检查空闲列表,如果空白,则处理该块。我不知道哪个往往更快 - 关于自上而下的免费列表的好处是它是缓存友好的,因为你使用的是最近使用的内存,所以我可能会尝试第一。

Note that the list node is not needed while the cell is allocated, so there's essentially zero overhead per cell. Quite aside from speed, this is likely to be an advantage over malloc, or other general-purpose allocators.

请注意,在分配单元时不需要列表节点,因此每个单元的开销基本上为零。除了速度之外,这可能比malloc或其他通用分配器更具优势。

Do be aware that dropping the whole allocator is pretty much the only way to release memory back to the system, so users who are planning to allocate a lot of cells, use them, and free them all, should create their own allocator, use it, and then destroy it. Both for performance (you don't have to free all the cells) and to prevent the fragmentation-style effect where a whole block must be kept if any of its cells are in use. If you can't do this, your memory use will be the high-water-mark of the time your program has been running. For some programs that's a problem (for instance a long-running program with occasional big spikes in memory use, on a system where memory is constrained). For others it's absolutely fine (for instance if the number of cells in use increases until very near the end of the program, or fluctuates within a range where you really don't care that you're using more memory than you strictly could). For some its actively desirable (if you know how much memory you're going to use, you can allocate it all up-front and not have to worry about failures). For that matter, some implementations of malloc have difficulty releasing memory back from the process to the OS.

请注意,丢弃整个分配器几乎是将内存释放回系统的唯一方法,因此计划分配大量单元,使用它们并释放所有单元的用户应该创建自己的分配器,使用它,然后摧毁它。两者都是为了性能(您不必释放所有单元格)并防止碎片式效果,如果任何单元格正在使用中,必须保留整个块。如果你不能这样做,你的记忆使用将是你的程序运行时间的最高标记。对于某些有问题的程序(例如长时间运行的程序,内存使用偶尔会出现大量峰值,在内存受限的系统上)。对于其他人来说,它绝对没问题(例如,如果使用的细胞数量增加,直到非常接近程序结束,或者在你真正不关心你使用的内存超出你的严格要求的范围内波动)。对于一些它的主动需求(如果你知道你将要使用多少内存,你可以预先分配它,而不必担心失败)。就此而言,malloc的某些实现难以将内存从进程释放回OS。

[*] Where "start of the the block" probably means "the start of the block, plus the size of some node used to maintain a list of all blocks, so they can all be freed when the cell allocator is destroyed".

[*]其中“块的开始”可能意味着“块的开始,加上用于维护所有块列表的某个节点的大小,因此当单元分配器被销毁时它们都可以被释放”。

#2


4  

Before embarking on the onerous task of re-writing malloc, the standard advice applies. Profile your code, and make sure that this is actually a problem!

在开始重写malloc的繁重任务之前,标准建议适用。描述您的代码,并确保这实际上是一个问题!

#3


4  

The best way to do this is to not assume it will be inefficient. Instead try out the solution with malloc, measure the performance and prove that it is either efficient or not. Then once it's provide to be innefficient (likely won't be) is the only time you should move to a custom allocator. Without the proof you'll never know if your solution is actually faster or not.

这样做的最好方法是不要假设它效率低下。而是尝试使用malloc解决方案,测量性能并证明它有效或无效。然后,一旦它提供的效率不高(可能不会)是唯一一次你应该转移到自定义分配器。没有证据,你永远不会知道你的解决方案是否真的更快。

#4


3  

for your requirement your custom allocator would be really simple. just calloc a large array memory

根据您的要求,您的自定义分配器非常简单。只是calloc一个大型数组内存

calloc(N * 16)

and then you can just hand out array entries. inorder to track which array locations are in use you could use a simple bitmap and then with a few clever bit operations and pointer subtraction your custom malloc/free operations should be pretty easy. if you run out of space you can just realloc some more, but having a suitable fixed default would be a little easier.

然后你可以分发数组条目。为了跟踪正在使用的数组位置,您可以使用一个简单的位图,然后使用一些聪明的位操作和指针减法,您的自定义malloc / free操作应该非常简单。如果你的空间不足你可以再重新分配一些,但是有一个合适的固定默认值会更容易一些。

though really you should just use malloc first. malloc creates pools of free memory blocks of different sizes, i would bet that there is a pool for 16 byte memory blocks (different implementations may or may not do this but its a pretty common optimization) and since all your allocations are the same size fragmentation should not be an issue. (plus debugging your allocator might be a bit of a nightmare.)

虽然你真的应该先使用malloc。 malloc创建了不同大小的可用内存块池,我敢打赌,有一个16字节内存块的池(不同的实现可能会或可能不会这样做,但它是一个非常常见的优化),因为所有的分配都是相同大小的碎片应该不是问题。 (加上调试你的分配器可能有点噩梦。)

#5


2  

What you're looking for is called a memory pool. There are existing implementations, although it's not hard (and good practice) to make your own.

您正在寻找的是一个内存池。有现成的实现,虽然创建自己的实现并不困难(和良好实践)。

The simplest implementation for a pool of same-sized data is just a wrapper containing a buffer of n*size, and a stack of n pointers. "malloc" from the pool pops the pointer off the top. "free" to the pool puts the pointer back into the stack.

对于相同大小的数据池,最简单的实现只是一个包含n *大小的缓冲区和一堆n个指针的包装器。池中的“malloc”将指针从顶部弹出。 “free”到池中会将指针放回堆栈中。

#6


1  

You could try overriding malloc/free with an alternative implementation that's suited to lots of small allocations.

您可以尝试使用适合大量小分配的替代实现来覆盖malloc / free。

#7


1  

Due to academic interest I was working on a solution to that problem a few days ago. The implementation is very simple but complete and you mentioned that you are looking for a drop-in replacement, so I think my implementation could work for you.

由于学术兴趣,我几天前正致力于解决这个问题。实现非常简单但完整,你提到你正在寻找替代品,所以我认为我的实现可能对你有用。

Basically it works like patros described, except that it automatically requests more memory if there are no free blocks any more. The code was tested with a large linked list (about 6 millon nodes, each 16 bytes in sizes) against a naive malloc()/free() scheme and performed roughly 15% faster than that. So supposedly it is usable for your intention. It is easy to adjust it to different block-sizes, since the block size specified when creating such a large chunk of memory.

基本上它就像描述的patros一样,只是如果没有空闲块就会自动请求更多的内存。该代码使用大型链表(大约6个节点,每个大小为16个字节)与一个天真的malloc()/ free()方案进行测试,并且执行速度比此快大约15%。所以据说它可以用于你的意图。由于在创建如此大的内存块时指定的块大小,因此很容易将其调整为不同的块大小。

The code is available on github: challoc

代码可以在github:challoc上找到

Example usage:

int main(int argc, char** argv) {
    struct node {
           int data;
       struct node *next, *prev;
    };
    // reserve memory for a large number of nodes
    // at the moment that's three calls to malloc()
    ChunkAllocator*  nodes = chcreate(1024 * 1024, sizeof(struct node));

    // get some nodes from the buffer
    struct node* head = challoc(nodes);
    head->data = 1;
    struct node* cur = NULL;
    int i;
    // this loop will be fast, since no additional
    // calls to malloc are necessary
    for (i = 1; i < 1024 * 1024; i++) {
            cur = challoc(nodes);
        cur->data = i;
        cur = cur->next;
    }

    // the next call to challoc(nodes) will
    // create a new buffer to hold double
    // the amount of `nodes' currently holds

    // do something with a few nodes here

    // put a single node back into the buffer
    chfree(nodes,head);

    // mark the complete buffer as `empty'
    // this also affects any additional
    // buffers that have been created implicitly
    chclear(nodes);

    // give all memory back to the OS
    chdestroy(nodes);

    return 0;
}

#8


0  

Wilson, Johnstone, Neely, and Boles wrote a nice paper surveying all sorts of different allocators.

Wilson,Johnstone,Neely和Boles写了一篇很好的论文,调查各种不同的分配器。

In my experience, the performance and overhead difference between a good fixed pool allocator and just relying on dlmalloc can be massive in cases where you're making lots and lots of short-lived small allocations in a limited address space (such as a system with no page file). In the app I'm working on at this moment, our main loop jumps from 30ms to >100ms if I replace our block allocator with simple calls to malloc() (and it eventually crashes due to fragmentation).

根据我的经验,一个好的固定池分配器和仅仅依赖于dlmalloc之间的性能和开销差异可能是巨大的,如果你在有限的地址空间(例如一个系统)中进行大量的短期小分配没有页面文件)。在我正在研究的应用程序中,如果我用简单的malloc()调用替换我们的块分配器,我们的主循环从30ms跳到> 100ms(并且它最终因碎片而崩溃)。

#9


0  

The following code is pretty ugly, but the purpose is not the beauty but to find out how big is the block allocated by malloc.
I asked for 4 bytes, and malloc requested and received 135160 bytes from OS.

下面的代码非常难看,但目的不是美观,而是要找出malloc分配的块有多大。我要求4个字节,并且malloc请求并从OS接收135160个字节。

#include <stdio.h>
#include <malloc.h>


int main()
{
  int* mem = (int*) malloc( sizeof(int) ) ;
  if(mem == 0) return 1;
  long i=1L;

  while(i)
    {
      mem[i-1] = i;
      printf("block is %d bytes\n", sizeof(int) * i++);
    }//while

  free(mem);
  return 0 ;
}

$ g++ -o file file.cpp
$ ./file
...
block is 135144 bytes
block is 135148 bytes
block is 135152 bytes
block is 135156 bytes
block is 135160 bytes
Segmentation fault

$ g ++ -o file file.cpp $ ./file ...块是135144字节块是135148字节块是135152字节块是135156字节块是135160字节分段错误

This malloc is serious business.
realloc doesn't do any system call if the requested size is less than it has available due to internal pooling.
After realloc copied the memory to a larger zone, it does nor destroy the previous block, not return it to system immediately. This can be still accessed (of course totally unsafe). With all these, it doesn't make sense to me, someone would need an additional memory pool.

这个malloc是严肃的事。如果请求的大小小于由于内部池而可用的大小,则realloc不会执行任何系统调用。在realloc将内存复制到更大的区域后,它也会破坏前一个块,不会立即将其返回给系统。这仍然可以访问(当然完全不安全)。有了这些,对我来说没有意义,有人需要一个额外的内存池。