C中的内存分配

时间:2009-10-31 18:12:39

标签: c memory-management malloc sbrk

以下是一个非常非常简单的 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;
}

3 个答案:

答案 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)

有一些问题:

  1. 您在函数中间声明pointer,这在C中是不允许的。

  2. 您将指针设置为stack+size,但您希望它只是stack。否则,您将返回指向您正在分配的内存块末尾的指针。因此,如果调用者在该指针处使用所有size个字节,则他将与另一个内存块重叠。如果你在不同的时间获得不同大小的块,你将有两个调用者试图使用相同的内存字节。

  3. 当您执行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中都是非法的。我甚至不知道我们可以从中得出什么结论:)

请确定您尝试使用的语言,我们将从那里开始。