在C中不使用malloc(使用sbrk或brk)将局部变量保存在堆上

在C中不使用malloc(使用sbrk或brk)将局部变量保存在堆上,c,linux,unix,operating-system,C,Linux,Unix,Operating System,我有一个结构如下: struct __attribute__((__packed__)) // compiler directive, avoid "gcc" padding bytes to struct meta_data { size_t size; // 8 bytes (in 64-bit OS) char free; // 1 byte ('f' or 'o') }; 结构的大小为9字节 我想使用sbrk

我有一个结构如下:

struct 
  __attribute__((__packed__)) // compiler directive, avoid "gcc" padding bytes to struct
  meta_data {
    size_t size;             // 8 bytes (in 64-bit OS)
    char free;               // 1 byte ('f' or 'o')
};
结构的大小为9字节

我想使用sbrk或brk在堆上分配9个字节,在堆上保存一个结构,并返回指向堆上动态分配的内存块的指针

目前我有这样的想法:

void *add(size_t size) {
  void* returnPointer;
  returnPointer = sbrk(9);
  struct meta_data newMetadata;
  newMetadata.size = size;
  newMetadata.free = 'o';
  return returnPointer;
}
此函数应该能够多次用于在堆上添加更多元数据块

但是,在这种情况下,当函数结束时,在函数内声明的局部变量newMetadata也会终止

如何将其保留在堆中,而不丢失对创建的新元数据的访问


注意:我不允许为此使用malloc。

通常的方法是模仿一些
malloc
包所做的。也就是说,将元数据放在比作为“数据”指针返回的地址更低的地址

以下是重构代码以实现此目的:

#include <unistd.h>

struct meta_data {
    size_t size;                        // 8 bytes (in 64-bit OS)
    char free;                          // 1 byte ('f' or 'o')
// compiler directive, avoid "gcc" padding bytes to struct
} __attribute__ ((__packed__));

void *
add(size_t size)
{
    struct meta_data *meta;
    void *returnPointer;

    meta = sbrk(sizeof(struct meta_data) + size);
    meta->size = size;
    meta->free = 'o';

    returnPointer = meta;
    returnPointer += sizeof(struct meta_data);

    return returnPointer;
}
#包括
结构元数据{
size\u t size;//8字节(在64位操作系统中)
无字符;//1字节('f'或'o')
//编译器指令,避免将字节“gcc”填充到结构
}_uuu属性_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
空虚*
添加(大小)
{
结构元数据*meta;
void*returnPointer;
meta=sbrk(sizeof(struct meta_data)+size);
元->大小=大小;
元->自由='o';
returnPointer=meta;
returnPointer+=sizeof(结构元数据);
返回指针;
}
请注意,大多数
malloc
替换将保证
returnPointer
为“出于任何目的对齐”,这通常意味着对齐到8字节边界(即
returnPointer
的低3位为0)


上面的代码不能做到这一点,因此您可以[稍后]添加它。

通常的方法是模仿一些
malloc
包所做的。也就是说,将元数据放在比作为“数据”指针返回的地址更低的地址

以下是重构代码以实现此目的:

#include <unistd.h>

struct meta_data {
    size_t size;                        // 8 bytes (in 64-bit OS)
    char free;                          // 1 byte ('f' or 'o')
// compiler directive, avoid "gcc" padding bytes to struct
} __attribute__ ((__packed__));

void *
add(size_t size)
{
    struct meta_data *meta;
    void *returnPointer;

    meta = sbrk(sizeof(struct meta_data) + size);
    meta->size = size;
    meta->free = 'o';

    returnPointer = meta;
    returnPointer += sizeof(struct meta_data);

    return returnPointer;
}
#包括
结构元数据{
size\u t size;//8字节(在64位操作系统中)
无字符;//1字节('f'或'o')
//编译器指令,避免将字节“gcc”填充到结构
}_uuu属性_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
空虚*
添加(大小)
{
结构元数据*meta;
void*returnPointer;
meta=sbrk(sizeof(struct meta_data)+size);
元->大小=大小;
元->自由='o';
returnPointer=meta;
returnPointer+=sizeof(结构元数据);
返回指针;
}
请注意,大多数
malloc
替换将保证
returnPointer
为“出于任何目的对齐”,这通常意味着对齐到8字节边界(即
returnPointer
的低3位为0)


上面的代码不能做到这一点,因此您可以[稍后]添加它。

newMetadata
设置为指针,并将其指向
sbrk
返回的新内存。只有malloc实现才允许使用非零参数调用
sbrk
。除非您正在编写一个完整的malloc实现,否则请改为使用
mmap
(如果这是一个家庭作业,而不是编写一个完整的malloc实现的作业,并且您被特别告知要使用
sbrk
,那么该作业有问题,您可以告诉您的讲师我是这么说的。)(附录:除了
sbrk
本身之外,任何人都不允许呼叫
brk
。)将
newMetadata
设为指针,并使其指向由
sbrk
返回的新内存。只有malloc实现才允许使用非零参数调用
sbrk
。除非您编写的是完整的malloc实现,否则使用
mmap
执行此操作。(如果这是一项家庭作业,而不是编写一个完整的malloc实现的作业,并且你被特别告知要使用
sbrk
,那么这个作业是有问题的,你可以告诉你的老师我是这么说的。)(增编:除了
sbrk
本身之外,任何人都不允许调用
brk
。)
returnPointer+=…
应该避免,因为C没有在
void*
上定义算术,你可以做
struct meta\u data*returnPointer;returnPointer=meta;returnPointer++;returnPointer;
应该避免
returnPointer+=…
,因为C没有在
void*
上定义算术,你可以这样做
struct meta_data*returnPointer;returnPointer=meta;returnPointer++;returnPointer;