以下是一个非常非常简单的 malloc()版本,似乎给我分配了一些空间,但除了没有free()之外我不检查是否我已超出分配的空间,如何检查代码是否正确?
“C”专家会打击我的任何明显错误?
#include <stdio.h>
#include <unistd.h>
#define MAX_MEMORY 1024 * 1024 * 2 /* 2MB of memory */
void *stack = NULL; /* pointer to available stack */
void * memoryAlloc(size) {
if (stack == NULL)
stack = sbrk(MAX_MEMORY); /* give us system memory */
void *pointer;
pointer = (void *)stack + size; /* we always have space :) */
stack += size; /* move in stack forward as space allocated */
return pointer;
}
答案 0 :(得分:11)
除了Ned Batchelder指出的基本问题之外,一个更微妙的问题是分配器必须返回一个地址,该地址与正在分配的任何对象正确对齐。在某些平台(x86)上,除了性能问题之外,这可能无关紧要,但在许多平台上,这是一个完全的交易破坏者。
我还必须执行(char*)
强制转换来执行stack
指针算术(你不能对void*
类型进行指针算法)。
你应该在MAX_MEMORY
宏的表达式周围放置一些parens。我不认为没有它们会有任何优先级问题,因为除了乘法之外的所有高优先级运算符都不是正确的语法。使用宏,始终比抱歉更安全。 (至少有一个例外,[]
运算符只能绑定到2
而不是整个MAX_MEMORY
表达式,但看到MAX_MEMORY[arrayname]
这将是一个非常奇怪的情况,即使它在语法上有效)。
事实上,我会把它作为一个枚举。
你可以通过返回一个为系统上任何基本数据类型正确对齐的内存块(可能是8字节对齐)来简化分配器:
/* Note: the following is untested */
/* it includes changes suggested by Batchelder */
#include <stdio.h>
#include <unistd.h>
enum {
kMaxMemory = 1024 * 1024 * 2, /* 2MB of memory */
kAlignment = 8
};
void *stack = NULL; /* pointer to available stack */
void * memoryAlloc( size_t size) {
void *pointer;
size = (size + kAlignment - 1) & ~(kAlignment - 1); /* round size up so allocations stay aligned */
if (stack == NULL)
stack = sbrk(kMaxMemory); /* give us system memory */
pointer = stack; /* we always have space :) */
stack = (char*) stack + size; /* move in stack forward as space allocated */
return pointer;
}
答案 1 :(得分:6)
有一些问题:
您在函数中间声明pointer
,这在C中是不允许的。
您将指针设置为stack+size
,但您希望它只是stack
。否则,您将返回指向您正在分配的内存块末尾的指针。因此,如果调用者在该指针处使用所有size
个字节,则他将与另一个内存块重叠。如果你在不同的时间获得不同大小的块,你将有两个调用者试图使用相同的内存字节。
当您执行stack += size
时,您的stack
不是递增size
个字节,而是递增size
void *,这几乎总是更大。
答案 2 :(得分:2)
首先,正如其他人已经注意到的那样,你在块的中间声明了变量,这只能在C99中使用,而不能在C89 / 90中使用。即我们必须得出结论你正在使用C99。
其次,您正在以K&amp; R风格(无参数类型)定义您的函数,但同时不会在以后声明参数类型。这样你就依赖于“隐含的int”规则,这在C99中是非法的。即我们必须得出结论,你的不是使用C99。这已经与“第一”部分相矛盾。 (此外,习惯使用 unsigned 类型来表示“对象大小”的概念。size_t
是通常用于此目的的专用类型。)
第三,你在void *
指针上使用指针算法,这在C89 / 90和C99中都是非法的。我甚至不知道我们可以从中得出什么结论:)
请确定您尝试使用的语言,我们将从那里开始。