Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 高效内存再分配问题_C_Memory Management_Performance_Malloc_Realloc - Fatal编程技术网

C 高效内存再分配问题

C 高效内存再分配问题,c,memory-management,performance,malloc,realloc,C,Memory Management,Performance,Malloc,Realloc,假设我有一个程序(例如C++),它分配多个对象,永远不会超过给定的大小(我们称之为MAX_OBJECT_size) 我在堆上也有一个区域(我称之为“页面”)(分配有malloc(region\u SIZE),其中region\u SIZE>=MAX\u OBJECT\u SIZE)。 我一直在那个页面中保留空间,直到填充的空间等于页面大小(或者至少得到>页面大小-最大对象大小) 现在,我想分配更多内存。显然,我以前的“页面”是不够的。所以我至少有两个选择: 使用realloc(页面,新大小),其

假设我有一个程序(例如C++),它分配多个对象,永远不会超过给定的大小(我们称之为MAX_OBJECT_size)

我在堆上也有一个区域(我称之为“页面”)(分配有malloc(region\u SIZE),其中region\u SIZE>=MAX\u OBJECT\u SIZE)。
我一直在那个页面中保留空间,直到填充的空间等于页面大小(或者至少得到>页面大小-最大对象大小)

现在,我想分配更多内存。显然,我以前的“页面”是不够的。所以我至少有两个选择:

  • 使用realloc(页面,新大小),其中新大小>页面大小
  • 分配一个新的“页面”(第2页)并将新对象放在那里
  • 如果我想要一个自定义分配函数,那么:

  • 使用第一种方法,我会看到我已经填充了多少,然后将我的新对象放在那里(并将对象的大小添加到填充的内存变量中)
  • 使用第二种方法,我将有一个页面列表(vector?array?),然后查找当前页面,然后在所选页面上使用类似于1的方法
  • 最终,我也需要一种释放内存的方法,但我能找到那一部分

    所以我的问题是:解决这样的问题最有效的方法是什么?是选项1、选项2还是我在这里没有考虑过的其他选项?是否需要/足够小的基准来针对现实情况得出结论?
    我知道不同的操作可能会执行不同的操作,但我正在寻找一个总体指标。

    从您的问题中不清楚为什么需要提前分配一大块内存,而不是根据需要为每个对象分配内存。我假设您将其用作连续数组。否则,根据需要对每个对象的内存进行
    malloc

    如果它确实起到数组的作用,
    malloc
    -调用另一个块将为您提供另一块内存,您必须通过另一个指针访问它(在您的例子中是
    page2
    )。因此,它不再位于连续块上,并且不能将这两个块用作一个数组的一部分

    另一方面,
    realloc
    ,分配一个连续的内存块。您可以将其用作单个数组,并执行各种指针运算,如果存在单独的块,则不可能执行这些运算
    realloc
    在您确实想要缩小正在使用的块时也很有用,但这可能不是您在这里想要做的


    因此,如果将其用作数组,
    realloc
    基本上是更好的选择。否则,
    malloc
    就没有问题了。实际上,您可能希望为您创建的每个对象使用
    malloc
    ,而不必跟踪和微管理内存块。

    您还没有给出您正在试验的平台的任何详细信息。例如,
    Linux
    Windows
    之间的
    realloc
    有一些性能差异

    根据情况,
    realloc
    如果不能增加当前内存块,并且将旧内存复制到新内存块,则可能必须分配一个新内存块,这是非常昂贵的。 如果您真的不需要连续的内存块,则应避免使用
    realloc

    我的建议是使用第二种方法,或者使用自定义分配器(您可以实现一个简单的方法)

    您还可以使用更高级的内存分配器,如


    在最坏的情况下,选项1可能会导致原始内存的“移动”,这是一项额外工作。如果内存没有移动,那么“额外”大小将被初始化,这也是另一项工作。因此,
    realloc
    将被malloc方法“击败”,但要说失败的程度,您应该进行测试(我认为在内存请求完成时,系统的运行方式存在偏差)

    根据需要执行realloc/malloc的次数,它可能是一个有用的想法,也可能是一个无用的想法。无论如何,我都会使用malloc

    自由战略取决于实施情况。要将所有页面作为一个整体释放,只需“遍历”它们就足够了;我不使用数组,而是使用链接的“页面”:将sizeof(void*)添加到“页面”大小,您可以使用额外的字节来存储指向下一页的指针


    如果您必须释放位于其中一个页面中任意位置的单个对象,它会变得稍微复杂一些。我的想法是保留一个非顺序自由“块”/“槽”(适合容纳任何对象)的列表。当请求新的“块”时,首先从该列表中弹出一个值;如果它是空的,那么您将在最后一个正在使用的页面中获得下一个“插槽”,并最终触发一个新页面。释放一个对象,意味着只需将空插槽地址放入堆栈/列表中(无论您喜欢使用什么)。

    根据我的经验,选项2更容易使用,开销最小。Realloc不保证它会增加现有内存的大小。在实践中,它几乎从来没有这样做过。如果使用它,则需要返回并重新映射所有旧对象。这需要你记住每个分配的对象在哪里。。。那可能比头顶高出一吨

    但如果不确切知道您使用的指标,就很难确定“最有效”

    这是我经常使用的内存管理器。它适用于整个应用程序,而不仅仅是一个对象

    allocs:

    对于每个分配,确定分配对象的大小

    1查看该大小对象的空闲链接列表,查看是否有任何内容已被释放,如果是,请获取第一个空闲

    2在查找表中查找,如果未找到

    2.1分配一个由N个被分配大小的对象组成的数组

    3返回所需大小的下一个自由对象

    3.1如果阵列已满,请添加新页面

    N个对象可以是p