5

以下是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;
}
4

3 回答 3

11

除了Ned Batchelder指出的基本问题之外,一个更微妙的问题是分配器必须返回一个地址,该地址与正在分配的任何对象都正确对齐。在某些平台 (x86) 上,除了性能问题之外,这可能无关紧要,但在许多平台上,这完全是破坏交易的因素。

我还必须执行(char*)强制转换来执行stack指针算术(你不能对void*类型执行指针算术)。

你应该在MAX_MEMORY宏中的表达式周围加上括号。我不认为没有它们你会遇到任何优先级问题,因为所有比乘法高优先级的运算符无论如何都不是正确的语法。使用宏,总是比抱歉更安全。(至少有一个例外,[]运算符只能绑定到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;
}
于 2009-10-31T18:31:28.737 回答
6

有几个问题:

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

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

  3. 当您这样做时stack += size,您stack不是按size字节递增,而是按sizevoid* 递增,这几乎总是更大。

于 2009-10-31T18:21:02.470 回答
2

首先,正如其他人已经指出的那样,您在块的中间声明变量,这仅在 C99 中允许,但在 C89/90 中不允许。即我们必须得出结论,您正在使用 C99。

其次,您正在以 K&R 样式(无参数类型)定义您的函数,但同时稍后不声明参数类型。这样,您就依赖于 C99 中禁止的“隐式 int”规则。即我们必须得出结论,您没有使用 C99。这已经和“第一”部分矛盾了。(此外,习惯上使用无符号类型来表示“对象大小”的概念。size_t是通常用于该目的的专用类型)。

第三,您在指针上使用指针算术void *,这在 C89/90 和 C99 中始终是非法的。我什至不知道我们能从中得出什么结论:)

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

于 2009-10-31T18:33:57.903 回答