SGI STL 的内存池是如何回收 chunk 内存的?

发布于 2022-09-11 15:26:15 字数 2973 浏览 18 评论 0

SGI STL 中, 没有使用的内存会以链表的方式挂载在 free_list 中, 如果 free_list 中有足够的内存, 那么直接返回. 但是内存的回收并不一定是按照内存的申请顺序来的, 这就导致链表的第一个并不一定是 chunk 的头部内存

而如果要回收 chunk 部分的内存, 必须要知道其 malloc() 回传的头部地址, 然后将其传给 free(). 虽然这个地址一定会在 free_list 中存在, 但是如何知道呢? 目前唯一能够想到的方法就是有一个动态的 void *[] 数组, 记录头部地址

因为在 chunk_alloc() 中, 如果出现 start_free == end_free 的情况, 在有足够内存的情况下, 也就是 malloc() 成功, start_freeend_free 都会被覆盖. 而 chunk_alloc() 函数中并没有任何操作是去记录原来的地址的

因此, 我查看了 STLport 5.2.1 中 allocators.cpp 的源码, 有关 chunk 内存的回收, 我找到这些代码 :

void __node_alloc_impl::_S_chunk_dealloc() {
  _Obj *__pcur = _S_chunks, *__pnext;
  while (__pcur != 0) {
    __pnext = __pcur->_M_next;
    __stlp_delete_chunck(__pcur);
    __pcur = __pnext;
  }
  _S_chunks = 0;
  _S_start_free = _S_end_free = 0;
  _S_heap_size = 0;
  memset(__REINTERPRET_CAST(char*, __CONST_CAST(_Obj**, &_S_free_list[0])), 0, _STLP_NFREELISTS * sizeof(_Obj*));
}

以及

void __node_alloc_impl::_S_chunk_dealloc() {
  // Note: The _Node_alloc_helper class ensures that this function
  // will only be called when the (shared) library is unloaded or the
  // process is shutdown.  It's thus not possible that another thread
  // is currently trying to allocate a node (we're not thread-safe here).
  //

  // Clear the free blocks and all freelistst.  This makes sure that if
  // for some reason more memory is allocated again during shutdown
  // (it'd also be really nasty to leave references to deallocated memory).
  _S_free_mem_blocks.clear();
  _S_heap_size      = 0;

  for (size_t __i = 0; __i < _STLP_NFREELISTS; ++__i) {
    _S_free_list[__i].clear();
  }

  // Detach list of chunks and free them all
  _Obj* __chunk = _S_chunks.clear();
  while (__chunk != 0) {
    _Obj* __next = __chunk->_M_next;
    __stlp_delete_chunck(__chunk);
    __chunk  = __next;
  }
}

一样的名称, 所以肯定是由 macro 进行选择

与 《STL 源码剖析》中相对应的 chunk_dealloc() 应该是第一段

在第一段中, 其实就是不断地去 __stlp_delete_chunck(__pcur); 但实际上这个函数只是调用 free() 或者 ::operator delete(), 对于 free_list 中每一小段内存都是用 free() 或者 ::operator delete(). 这好像是不可行的, 所以对此, 我写了一小段 demo :

#include <iostream>

using namespace std;
union x {
    x *next;
    char client_data[0];
};
int main(int argc, char *argv[]) {
    auto p {malloc(sizeof(x) * 2)};
    auto x_ptr1 {static_cast<x *>(p)};
    auto x_ptr2 {static_cast<x *>(p) + 1};
    free(x_ptr2);
    free(x_ptr1);
}

最终的结果就是 pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
Terminated due to signal: ABORT TRAP (6)

所以这并不可行

想请教各位, SGI STL 最终是如何对 chunk 内存进行回收的?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮萍、无处依 2022-09-18 15:26:15

答案是不释放,由 OS 负责回收
之前问了不少人,有些人没懂有些人给出错误答案

https://jonny.vip/2019/07/16/...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文