C: malloc 和 free 的堆栈实现

C: Stack implementation of malloc and free

我正在阅读 K&R 指针第 5.4 节,其中完成了 malloc()free() 的堆栈实现。我正在使用 gdb 调试代码,alloc() 部分按预期工作。但是对于 afree() 部分,指针仍然指向与之前相同的位置。这是代码:

#include <stdio.h>
#define ALLOCSIZE 10000

static char allocbuf[ALLOCSIZE];
static char* allocp = allocbuf;

char* alloc(int n)
{
    if(allocbuf + ALLOCSIZE - allocp >= n)
    {   
        allocp += n;
        return (allocp - n); 
    }   
    else
        return 0;
}


void afree(char* p)
{
    if(p >= allocbuf && p < allocbuf + ALLOCSIZE)
        allocp = p;
}


int main()
{
    char* a = alloc(10);
    a = "ayushnair";
    char*b = alloc(5);
    b = "snea";
    printf("%p    %p\n", a, b); 
    afree(b);
    afree(a);
    printf("%p    %p\n", a, b); 
    return 0;
}

新分配

allocp 0x601080

char* a = alloc(10);

之后

allocp 0x60108a

char* b = alloc(5);

之后

allocp 0x60108f

afree(b);

之后

allocp 0x60108f

afree(a);

之后

allocp 0x60108f

allocp 仍然指向 0x60108f。为什么不按代码更新?

在你的代码中,说

a = "ayushnair";

您没有将 "ayushnair" 存储到 a 指向的内存中。 "ayushnair" 是一个 字符串文字 并且说

a = "ayushnair";

您正在将字符串文字的基地址存储到 a 中。这样,您实际上是通过调用 alloc().

覆盖返回的指针

这不是你想要的。您可能需要使用 strcpy() 将字符串文字 复制到 返回的指针中。

也就是说,根据当前代码,稍后调用

afree(b);
afree(a);

您正在调用 undefined behavior,因为您正在尝试比较不指向同一对象的指针。

引用 C11,章节 §6.5.8,关系运算符

When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.

它不会更新指针(在 afee 上),因为这种内存分配器算法是渐进的,并且具有 "no memory" 个先前分配的内存部分。因此 returns 只是指向未使用内存的指针。分配 ALLOCSIZE 后,将无法分配更多内存。大多数内存分配器都会对消耗的内存做出一些假设。

char* a = alloc(10);

来自 allocbuf 的 "allocates" 内存,并将指向该内存的指针分配给 a

a = "ayushnair";

这将一个 不同的 指针分配给 a -- 指向字符串文字 "ayushnair" 的指针, 不在allocbuf 但完全在内存中的其他地方。

从现在开始,您的程序变得越来越混乱(尤其是因为您在 b 中犯了类似的错误)。对 afree( a ) 的调用没有意义,因为 a 不再指向 alloc() 返回的内容,并且 afree() 所做的比较实际上调用了未定义的行为,正如 Sourav Ghosh 指出的那样 - - 但错误是 a = "ayushnair"(以及对 b 的类似赋值)。


C 语言没有 "string object" 的概念,只是一个约定,指向以 '[=26=]' 结尾的 char 序列的指针称为 "string" 并有一些支持功能。运算符 = 的适当定义意味着 "copy the contents" 是 而不是 那些支持函数的一部分。

想要做的是:

char * a = alloc( 10 );
strcpy( a, "ayushnair" );

那会从字符串文字复制a指向的内存。


所以,最重要的是,您的问题与逻辑运算符或比较运算符无关,也与数组无关,而是与指针和字符串有关。我希望我能澄清一点。