为什么删除的内存无法重复使用 [英] Why is deleted memory unable to be reused

查看:124
本文介绍了为什么删除的内存无法重复使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Windows 7上使用C ++的MSVC 9.0,并已经能够测试和重现在Windows XP SP3与MSVC 9.0。

I am using C++ on Windows 7 with MSVC 9.0, and have also been able to test and reproduce on Windows XP SP3 with MSVC 9.0.

如果我分配1 GB的0.5 MB大小的对象,当我删除它们,一切都是确定和行为正如预期。但是,如果我在删除它们时分配1 GB的0.25 MB大小的对象,则内存将保留(在地址空间监视器< a>),从那时起只能用于小于0.25 MB的分配。

If I allocate 1 GB of 0.5 MB sized objects, when I delete them, everything is ok and behaves as expected. However if I allocate 1 GB of 0.25 MB sized objects when I delete them, the memory remains reserved (yellow in Address Space Monitor) and from then on will only be able to be used for allocations smaller than 0.25 MB.

这个简单的代码将允许你通过改变哪个struct typedef'd。在分配和删除结构之后,它将分配1 GB的1 MB char缓冲区,以查看char缓冲区是否将使用结构体曾占用的内存。

This simple code will let you test both scenarios by changing which struct is typedef'd. After it has allocated and deleted the structs it will then allocate 1 GB of 1 MB char buffers to see if the char buffers will use the memory that the structs once occupied.

struct HalfMegStruct
{
    HalfMegStruct():m_Next(0){}

    /* return the number of objects needed to allocate one gig */
    static int getIterations(){ return 2048; }

    int m_Data[131071];
    HalfMegStruct* m_Next;
};

struct QuarterMegStruct
{
    QuarterMegStruct():m_Next(0){}

    /* return the number of objects needed to allocate one gig */
    static int getIterations(){ return 4096; }

    int m_Data[65535];
    QuarterMegStruct* m_Next;
};

// which struct to use
typedef QuarterMegStruct UseType;

int main()
{
    UseType* first = new UseType;
    UseType* current = first;

    for ( int i = 0; i < UseType::getIterations(); ++i )
        current = current->m_Next = new UseType;

    while ( first->m_Next )
    {
        UseType* temp = first->m_Next;
        delete first;
        first = temp;
    }

    delete first;

    for ( unsigned int i = 0; i < 1024; ++i )
        // one meg buffer, i'm aware this is a leak but its for illustrative purposes. 
        new char[ 1048576 ]; 

    return 0;
}



下面你可以从
地址空间监视器。让我强调,这两个最终结果之间的唯一区别是分配到1 GB标记的结构的大小。

Below you can see my results from within Address Space Monitor. Let me stress that the only difference between these two end results is the size of the structs being allocated up to the 1 GB marker.

< img src =http://i.stack.imgur.com/7lPBw.pngalt =Quarter Meg>

这对我来说似乎是一个严重的问题,很多人可能正在忍受,甚至不知道。

This seems like quite a serious problem to me, and one that many people could be suffering from and not even know it.


  • 这是设计还是应该被视为错误?


  • 出于好奇,Mac或Linux机器是否也遇到同样的问题?

推荐答案

我不能肯定地说这是case,但这看起来像内存碎片(在其多种形式之一)。分配器(malloc)可能保持不同大小的桶来启用快速分配,在释放内存之后,而不是直接将其返回到保持桶的操作系统,以便以后的相同大小的分配可以从相同的内存。

I cannot positively state this is the case, but this does look like memory fragmentation (in one of its many forms). The allocator (malloc) might be keeping buckets of different sizes to enable fast allocation, after you release the memory, instead of directly giving it back to the OS it is keeping the buckets so that later allocations of the same size can be processed from the same memory. If this is the case, the memory would be available for further allocations of the same size.

这种类型的优化 通常被禁用 对象,因为它需要保留内存,即使没有使用。如果阈值在你的两个大小之间,这将解释行为。

This type of optimization, is usually disabled for big objects, as it requires reserving memory even if not in use. If the threshold is somewhere between your two sizes, that would explain the behavior.

请注意,虽然你可能会看到这是奇怪的,但在大多数程序(不测试,但现实生活)内存使用模式重复:如果你要求100k块一次,它更经常是不是的情况下,你会做它再次。并保留内存保留可以提高性能,并实际减少来自同一存储桶中所有请求的碎片。

Note that while you might see this as weird, in most programs (not test, but real life) the memory usage patterns are repeated: if you asked for 100k blocks once, it more often than not is the case that you will do it again. And keeping the memory reserved can improve performance and actually reduce fragmentation that would come from all requests being granted from the same bucket.

你可以,如果你想投入一些时间,通过分析行为来了解你的分配器的工作原理。编写一些测试,将获取大小X,释放它,然后获取大小Y,然后显示内存使用情况。修复X的值并与Y一起播放。如果两个大小的请求都从同一个桶中授予,则不会有保留/未使用的内存(左侧的图片),而在从不同桶中授予的大小时,对右边的图像的影响。

You can, if you want to invest some time, learn how your allocator works by analyzing the behavior. Write some tests, that will acquire size X, release it, then acquire size Y and then show the memory usage. Fix the value of X and play with Y. If the requests for both sizes are granted from the same buckets, you will not have reserved/unused memory (image on the left), while when the sizes are granted from different buckets you will see the effect on the image on the right.

我通常不会为窗口编码,我甚至没有Windows 7,所以我不能肯定地说,这是的,但它看起来像这样。

I don't usually code for windows, and I don't even have Windows 7, so I cannot positively state that this is the case, but it does look like it.

这篇关于为什么删除的内存无法重复使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆