背景: 我正在完成一个项目,其目标是构建一个复制 malloc() 和 free() 的内存管理系统。该程序首先使用 mmap 从操作系统请求指定数量的内存,然后使用链表来跟踪哪些内存部分正在使用或空闲。请参阅下文,大致了解我在做什么。
Output after allocating one chunk of memory
问题 为什么我在尝试创建一个新的列表节点来表示空闲内存时会遇到段错误?只有在尝试请求两个以上的内存块时才会发生此段错误 - 第一个按预期工作。
详细信息 当试图为刚创建的节点(下面代码中的 new)的属性赋值以表示剩余的可用内存空间时,会发生段错误。第一次将内存拆分为已用 v. 空闲段时,此分配有效,但第二次尝试将空闲内存拆分为已用 v. 空闲段时,我的程序遇到段错误 - 我假设发生这种情况是因为属性新的 node_t 结构未定义(编译器不知道它们在内存中的位置)。 我不知道为什么会发生这种情况,以及为什么在我第一次使用此代码时没有发生这种情况。
注意: 答案不应该是在初始化 *new 节点时使用 malloc,因为项目的重点是在不使用 malloc 的情况下执行此操作。 Malloc 不会从我正在管理的内存中分配 - 相反,它会从我的程序实际维护(但不使用)的堆中分配。
结构定义:
typedef enum {false, true} bool;
typedef struct _node_t {
int size;
struct _node_t *next;
struct _node_t *prev;
bool used;
} node_t;
问题代码。 ret 是我要返回给调用者的内存分配,new 是我刚刚分配的空闲内存块的剩余部分。
// Code above this steps through the list elements to find the first free
// element that is large enough. I've debugged enough to know that's not the
// source of the problem.
node_t *new = ret + sizeof(node_t) + size; // Pointer to new free slot
assert(new != NULL);
new->prev = ret;
new->next = ret->next;
new->size = ret->size - sizeof(node_t) - size;
new->used = false;
ret->used = true;
ret->next = new;
ret->size = size;
return (ret + sizeof(node_t));
调用代码:
int main(int argc, char* argv[]) {
int success = Mem_Init(5000, P_FIRSTFIT);
if (success == -1)
return -1;
int *slot1 = Mem_Alloc(sizeof(int));
// This is where segmentation fault occurs
int *slot2 = Mem_Alloc(sizeof(int));
Link编写可以编译和运行的代码。
最佳答案
虽然您没有包含 ret
的定义并且 Dropbox 对于在智能手机上查看代码完全没有用,但我认为我们可以推断出声明
node_t* ret;
否则 ret->next
将无法编译。
在这种情况下,ret + sizeof(node_t)
没有意义,因为 C 中指针运算的性质。请记住 p + k
完全相同作为 &p[k]
。换句话说,p + 1
是下一个大小为 sizeof*p
的元素的地址。所以ret + sizeof(node_t)
是ret
之后第16个或第32个元素的地址,取决于sizeof(node_t)
。
您可能想要的是 ret + 1
,它的简单性说明了 C 指针算法背后的基本原理。
关于c - 尝试复制 malloc 时遇到段错误问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42888288/