代码之家  ›  专栏  ›  技术社区  ›  Radek

C中的内存分配

  •  5
  • Radek  · 技术社区  · 15 年前

    以下是一个非常简单的版本 马尔洛() 似乎给我分配了一些空间,但是除了没有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 回复  |  直到 15 年前
        1
  •  11
  •   Community Egal    7 年前

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

    我还得表演 (char*) 演员表演 stack 指针算术(不能在上执行指针算术 void* 类型)。

    你应该把帕伦斯放在 MAX_MEMORY 宏。我不认为没有它们你会遇到任何优先级问题,因为所有比乘法优先级高的运算符都不会是正确的语法。有了宏, 总是 安全总比抱歉好。(至少有一个例外 [] 运算符只能绑定到 2 而不是整个 最大内存 表情,但这是一个非常奇怪的情况 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;
    }
    
        2
  •  6
  •   Ned Batchelder    15 年前

    有几个问题:

    1. 你宣布 pointer 在函数的中间,这在C中是不允许的。

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

    3. 当你这样做的时候 stack += size ,你在增加 堆栈 不被 大小 字节但通过 大小 空*,几乎总是更大。

        3
  •  2
  •   AnT stands with Russia    15 年前

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

    其次,您要用k&r样式定义函数(没有参数类型),但同时以后不声明参数类型。这样你就依赖于“隐式int”规则,这在C99中是非法的。也就是说,我们必须得出结论 使用C99。这已经是与“第一”部分的矛盾了。(此外,习惯上使用 未签名的 表示“对象大小”概念的类型。 size_t 是一种专用类型,通常用于此目的)。

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

    请决定你要用什么语言,我们就从那里开始。