C中的内存分配
下面是 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;
}
the following is a very very simple version of malloc() and seems to allocate some space to me, but apart from the fact that there is no free() and I don't check if I've overrun the allocated space, how can I check that the code is correct?
Any obvious blunders that "C" experts would slap me for?
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
除了 Ned Batchelder 指出的基本问题之外,一个更微妙的问题是分配器必须返回一个与正在分配的任何对象正确对齐的地址。在某些平台(x86)上,除了性能问题外,这可能并不重要,但在许多平台上,这完全是一个问题。
我还必须执行
(char*)
强制转换来执行stack
指针算术(您不能对void*
类型进行指针算术) )。并且您应该在
MAX_MEMORY
宏中的表达式两边加上括号。我认为如果没有它们,您不会遇到任何优先级问题,因为所有比乘法优先级高的运算符无论如何都不是正确的语法。对于宏,总是安全总比后悔好。 (至少有一个例外,[]
运算符只能绑定到2
而不是整个MAX_MEMORY
表达式,但这将是一个看到 MAX_MEMORY[arrayname] 的情况非常奇怪,即使它在语法上是有效的)。事实上,我会把它变成一个枚举。
您可以通过返回与系统上的任何基本数据类型正确对齐的内存块(可能是 8 字节对齐)来保持分配器简单:
In addition to the basic problems Ned Batchelder pointed out, a much more subtle problem is that an allocator has to return an address that's properly aligned for whatever object is being allocated. On some platforms (x86) this may not matter except for performance issues, but on many platforms it's a complete deal breaker.
I also had to perform a
(char*)
cast to perform thestack
pointer arithmetic (you can't do pointer arithmetic onvoid*
types).And you should put parens around the expression in the
MAX_MEMORY
macro. I don't think there are any precedence problems you'd get into without them, as all the high precedence operators than multiplication wouldn't be correct syntax anyway. With macros, it's always better safe than sorry. (There's at least one exception where the[]
operator could bind only to the2
and not the wholeMAX_MEMORY
expression, but it would be a very weird situation to seeMAX_MEMORY[arrayname]
, even if it's syntactically valid).As a matter of fact, I would have made it an enum.
You can probably keep the allocator simple by returning a block of memory that's properly aligned for any basic data type on the system (maybe an 8 byte alignment):
有一些问题:
您在函数中间声明
pointer
,这在 C 中是不允许的。您将指针设置为
stack+size
,但您希望它只是stack
。否则,您将返回一个指向您正在分配的内存块末尾的指针。因此,如果您的调用者使用该指针处的所有size
字节,他将与另一个内存块重叠。如果您在不同时间获得不同大小的块,则会有两个调用者尝试使用相同字节的内存。当您执行
stack += size
时,您不是按size
字节而是按sizestack
> void*'s,它几乎总是更大。There are a few problems:
You declare
pointer
in the middle of the function, which isn't allowed in C.You set pointer to
stack+size
, but you want it to be juststack
. Otherwise, you're returning a pointer to the end of the block of memory you're allocating. As a result, if your caller uses allsize
bytes at that pointer, he'll be overlapping with another block of memory. If you get different sized blocks at different times, you'll have two callers trying to use the same bytes of memory.When you do
stack += size
, you're incrementingstack
not bysize
bytes but bysize
void*'s, which is almost always larger.首先,正如其他人已经指出的,您在块的中间声明变量,这仅在 C99 中允许,但在 C89/90 中不允许。也就是说,我们必须得出结论,您正在使用 C99。
其次,您以 K&R 风格(无参数类型)定义函数,但同时稍后不声明参数类型。这样你就依赖于“隐式 int”规则,这在 C99 中是非法的。也就是说,我们必须得出结论,您没有使用C99。这已经和“第一”部分矛盾了。 (此外,习惯上使用无符号类型来表示“对象大小”的概念。
size_t
是通常用于此目的的专用类型)。第三,您在
void *
指针上使用指针算术,这在 C89/90 和 C99 中始终是非法的。我什至不知道我们可以从中得出什么结论:)请决定您要使用的语言,然后我们将从那里开始。
Firstly, as other have already noted, you are declaring variables in the middle of the block, which is only allowed in C99, but not in C89/90. I.e. we have to conclude that you are using C99.
Secondly, you are defining your function in K&R-style (no parameter type), but at the same time not declaring the parameter type later. That way you are relying on the "implicit int" rule, which is outlawed in C99. I.e. we have to conclude that your are not using C99. This is already a contradiction with the "firstly" part. (Additionally, it is customary to use unsigned types to represent the concept of "object size".
size_t
is a dedicated type normally used for that purpose).Thirdly, you are using pointer arithmetic on a
void *
pointer, which is always illegal in both C89/90 and C99. I don't even know what we can conclude from that :)Please, decide what language you are trying to use, and we will go from there.