malloc替代内存分配作为堆栈

时间:2015-07-04 05:19:31

标签: c multithreading memory malloc dynamic-memory-allocation

我正在寻找 c malloc 替代方案,它只能用作堆栈。更像是 alloca 但不受空间限制的堆栈大小。它用于编码数学算法。

  • 我将使用大量内存(在算法中间可能使用数百兆字节)
  • 以类似堆栈的顺序访问内存。我的意思是要释放的下一个内存始终是最近分配的内存。
  • 希望能够运行各种系统(Windows和类Unix)
  • 作为额外的,可以与线程一起使用的东西,其中类似堆栈的分配和空闲顺序仅适用于单个线程。 (理想情况下,每个线程都有自己的“池”用于内存分配)

我的问题是,有这样的东西,还是这个容易实现的东西?

3 个答案:

答案 0 :(得分:1)

正如您已经发现的那样,只要它与malloc一起使用,您就应该使用它,只有当您需要挤出最后一点性能时才会回来。

适合这种情况的想法:您可以使用在需要时分配的块列表。使用列表可以在达到虚拟内存限制时最终交换数据。

struct block {
  size_t size;
  void * memory;
  struct block * next;
};
struct stacklike {
  struct block * top;
  void * last_alloc;
};
void * allocate (struct stacklike * a, size_t s) {
  // add null check for top
  if (a->top->size - (a->next_alloc - a->top->memory) < s + sizeof(size_t)) {
    // not enough memory left in top block, allocate new one
    struct block * nb = malloc(sizeof(*nb));
    nb->next = a->top;
    a->top = nb;
    nb->memory = malloc(/* some size large enough to hold multiple data entities */);
    // also set nb size to that size
    a->next_alloc = nb->memory;
  }
  void * place = a->next_alloc;
  a->next_alloc += s;
  *((size_t *) a->next_alloc) = s; // store size to be able to free
  a->next_alloc += sizeof (size_t);
  return place;
}

我希望这显示出一般的想法,对于实际的实施,还有更多需要考虑的问题。

要将您更改的内容换成双向链接列表,请跟踪总分配字节数。如果达到限制,请将结尾写入某个文件。

答案 1 :(得分:1)

这听起来像是Obstack的完美用法。

我自己从未使用它,因为API真的令人困惑,我现在无法挖掘出一个例子。但它支持您想要的所有操作,并且还支持流“创建”当前“对象。

编辑:掀起一个简单的例子。 Obstack API显示年龄的迹象,但原则至少是健全的。

您可能希望调整对齐/阻止设置,如果您进行任何花哨的增长,可能会使用obstack_next_freeobstack_object_size

#include <obstack.h>
#include <stdio.h>
#include <stdlib.h>

void *xmalloc(size_t size)
{
    void *rv = malloc(size);
    if (rv == NULL)
        abort();
    return rv;
}

#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free

const char *cat(struct obstack *obstack_ptr, const char *dir, const char *file)
{
    obstack_grow(obstack_ptr, dir, strlen(dir));
    obstack_1grow(obstack_ptr, '/');
    obstack_grow0(obstack_ptr, file, strlen(file));
    return obstack_finish(obstack_ptr);
}

int main()
{
    struct obstack main_stack;
    obstack_init(&main_stack);
    const char *cat1 = cat(&main_stack, "dir1", "file1");
    const char *cat2 = cat(&main_stack, "dir1", "file2");
    const char *cat3 = cat(&main_stack, "dir2", "file3");
    puts(cat1);
    puts(cat2);
    puts(cat3);
    obstack_free(&main_stack, cat2);
    // cat2 and cat3 both freed, cat1 still valid
}

答案 2 :(得分:0)

我已经看到旧的FORTRAN程序中使用的策略可能正是您正在寻找的。该策略涉及使用从main传递给每个函数的全局数组。

char global_buffer[SOME_LARGE_SIZE];

void foo1(char* buffer, ...);
void foo2(char* buffer, ...);
void foo3(char* buffer, ...);

int main()
{
   foo1(global_buffer, ....);
}

void foo1(char* buffer, ...)
{
   // This function needs to use SIZE1 characters of buffer.
   // It can let the functions that it calls use buffer+SIZE1

   foo2(buffer+SIZE1, ...);

   // When foo2 returns, everything from buffer+SIZE1 is assumed
   // to be free for re-use.
}

void foo2(char* buffer, ...)
{
   // This function needs to use SIZE2 characters of buffer.
   // It can let the functions that it calls use buffer+SIZE2

   foo3(buffer+SIZE2, ...);
}

void foo3(char* buffer, ...)
{
   // This function needs to use SIZE3 characters of buffer.
   // It can let the functions that it calls use buffer+SIZE3

   bar1(buffer+SIZE3, ...);
}