我正在寻找 c 的 malloc 替代方案,它只能用作堆栈。更像是 alloca 但不受空间限制的堆栈大小。它用于编码数学算法。
我的问题是,有这样的东西,还是这个容易实现的东西?
答案 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_free
和obstack_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, ...);
}