首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不同行为的马洛和自由?

不同行为的马洛和自由?
EN

Stack Overflow用户
提问于 2017-10-01 12:48:49
回答 3查看 327关注 0票数 1

我有一个用C++实现的树。

当我运行创建树的代码并使用malloc()插入大约5,000,000 int键时,当我使用Visual 2013运行时,它将使用类似于200 as的(如任务管理器所示)。

当我在每个节点上使用free()释放树时,它将返回到0.5MB的周围。到现在为止一切都还好。

现在,当我使用cygwin编译和运行Visual时,树的大小就像80 in (这是可以的,因为visual Studio添加了调试信息和其他东西),,但是当我释放树时,它的大小没有任何变化!

简单地说:在Visual中运行释放树时,将程序的大小返回到原始大小0.5MB,但是当我在Visual之外编译和运行相同的代码(使用cygwin)时,释放树不会从程序大小(仍然是80 of )中改变任何东西。

那为什么会发生这种事?

更新

释放树后,我尝试再次在树中插入相同的5,000,000 int键。在cygwin的情况下,它没有使用额外的内存,即相同的80 to,这意味着,正如反馈所指出的(谢谢各位+1),内存被释放了,但没有返回到操作系统。

现在的问题是:--如果我有大量内存分配,当释放的时候,我不喜欢把这个空闲的区域保留在程序中。那么,我如何让强制 cygwin将其返回到操作系统呢?

EN

回答 3

Stack Overflow用户

发布于 2017-10-01 12:54:04

不同的恶意行为是不同的。Microsoft可以使用原始堆分配和释放项。

看起来MS在直接原始堆(HeapAlloc/HeapFree)上使用内存。

但是cygwin使用的是本地托管内存系统。

这意味着通过HeapAlloc / HeapFree释放内存将返回给操作系统,并释放相关资源。

在cygwin上自由调用,将返回要重用的内存,但不会将其返回给操作系统。

管理大量内存

如果您有大量需要处理的内存,那么您最好直接管理它们,方法是迭代操作系统,并调用它的基本函数。例如,在Windows上,您可以调用HeapCreate来创建一个单独的堆,并使用HeapAlloc在该单独的大型块分配中分配,用HeapFree释放它们。

当您完成该块时,可以使用HeapDestroy释放所有内存。

票数 2
EN

Stack Overflow用户

发布于 2017-10-01 13:07:41

由于需要与其他进程交互(例如,与向实际管理硬件资源的特权设备驱动程序发出请求相关联的上下文切换),动态请求内存和释放内存可能是代价高昂的操作。

为了减少这种性能命中,malloc() (和calloc()等)和free()可以在内部管理分配的内存池,以避免每次请求或释放内存时访问操作系统的开销。例如,如果调用free(),它可能只是更改内部数据结构,以记录程序不再使用的内存块,但实际上并没有通知操作系统内存已被释放。

malloc()也可能故意过度分配。例如,它可能一次从主机系统请求数to,即使程序的请求要少得多,然后对多个malloc()调用进行阻塞,而不是为malloc()的每个调用向操作系统发出请求。

使用malloc()free()这样的工作方式,就操作系统而言,程序对free()调用的内存使用量可能不会减少(至少在free()代码根据自己的标准决定将内存返回给主机系统之前是这样的)。对于malloc()的多个调用,可能还会受到内存使用急剧增加的影响,然后会趋于平稳,即使程序多次调用malloc()而不调用free()

票数 1
EN

Stack Overflow用户

发布于 2017-10-01 15:05:27

通用内存分配程序使用各种启发式方法来尝试和优化常见的分配/去分配模式,但它们必须正确处理所有情况。

在您的特定情况下,如果您的问题具有以下属性,您可能有资格使用一种简单得多的方法:

  • 您分配了许多大小相同的对象。
  • 你把它们分配到一个阶段。
  • 您同时释放所有对象。

您可以使用自定义分配器来分配节点,并在批处理中释放节点。下面是一个示例:

代码语言:javascript
复制
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *left, right;
} Node;

typedef struct NodeBlock {
    struct NodeBlock *next;
    size_t count, size;
    Node a[32768];
} NodeBlock;

Node *alloc_node(NodeBlock **node_heapp) {
    NodeBlock *ptr = *node_heap;
    if (!ptr || ptr->count == ptr->size) {
        ptr = calloc(sizeof(*ptr, 1);
        if (ptr == NULL)
            return NULL;
        ptr->size = sizeof(ptr->a) / sizeof(ptr->a[0]);
        ptr->next = *node_heap;
        *node_heap = ptr;
    }
    return &ptr->a[ptr->count++];
}

void free_nodes(NodeBlock **node_heapp) {
    while (*node_heapp) {
        NodeBlock *ptr = *node_heap;
        *node_heap = ptr->next;
        free(ptr);
    }
}

上面的代码将节点分批分配:

  • 分配的效率更高,因为它只进行很少的系统调用,并且使用简单的方法返回下一个可用的时隙。
  • 头顶很小。
  • 取消分配也是非常快速的,因为不需要遍历树就可以释放单个节点。
  • 它在Unix系统上也可能具有很好的属性,因为malloc()很可能对大型请求使用mmap(),在取消分配时将内存交给系统。如果没有观察到这一点,请尝试增加阻塞因子( Node数组a的长度)。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46512510

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档