当剩余内存超过一定大小时,我的自定义malloc函数崩溃

当剩余内存超过一定大小时,我的自定义malloc函数崩溃,c,C,我尝试在C中创建自己的malloc函数,使用数组作为我将使用的内存。但是,当剩余内存大小超过一定数量的位时,程序崩溃,并说“抛出异常:写入访问冲突” 我把内存分成若干块。每个块将有一个小的元数据块,它保留块的大小以及它是空闲的还是占用的(在开始时,整个内存数组是一个大块)。 然后,我的malloc找到第一个具有足够大小的内存块并使用它(或它的一部分) 问题是: 例如,如果我初始化一个大小为20000字节的数组,那么只有当数组中剩余的可用字节数为17708或更多时,我的malloc才会工作 #in

我尝试在C中创建自己的malloc函数,使用数组作为我将使用的内存。但是,当剩余内存大小超过一定数量的位时,程序崩溃,并说“抛出异常:写入访问冲突”

我把内存分成若干块。每个块将有一个小的元数据块,它保留块的大小以及它是空闲的还是占用的(在开始时,整个内存数组是一个大块)。 然后,我的malloc找到第一个具有足够大小的内存块并使用它(或它的一部分)

问题是: 例如,如果我初始化一个大小为20000字节的数组,那么只有当数组中剩余的可用字节数为17708或更多时,我的malloc才会工作

#include <stdio.h>

char memory[20000];             

struct block {                  
    unsigned int size;
    int free;
    struct block* next;
};

struct block* freeList = (void*)memory;

void initialize() {             /
    freeList->size = 20000 - sizeof(struct block);
    freeList->free = 1;
    freeList->next = NULL;
}

void split(struct block* fitting_slot, unsigned int size) {         
    struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
    unsigned int temp = (fitting_slot->size) - size - sizeof(struct block);
    printf("Remaining memory size is %d\n", temp);

    new->size = temp;            // this is where program crashes
    new->free = 1;
    new->next = fitting_slot->next;
    fitting_slot->size = size;
    fitting_slot->free = 0;
    fitting_slot->next = new;
}


void* MyMalloc(unsigned int noOfBytes) {
    struct block* curr;
    void* result;
    if (!(freeList->size)) {
        initialize();
    }
    curr = freeList;

    while ((((curr->size) < (noOfBytes + sizeof(struct block))) || ((curr->free) == 0)) && (curr->next != NULL)) {          
        curr = curr->next;
    }
    printf("From the free memory of size : %d\n", curr->size);
    printf("We will occupy this size : %d\n", noOfBytes + sizeof(struct block));

    if ((curr->size) == (noOfBytes + sizeof(struct block))) {
        curr->free = 0;
        result = (void*)(++curr);
        printf("Exact fitting block allocated\n\n");
    }
    else if ((curr->size) > (noOfBytes + sizeof(struct block))) {
        split(curr, noOfBytes);
        result = (void*)(++curr);
        printf("Fitting block allocated with a split\n\n");
    }
    else {
        result = NULL;
        printf("Sorry. No sufficient memory to allocate\n\n");
    }
    return result;
}

int main(){
    unsigned int size = 2270 * sizeof(char);       
    char* k = (char)MyMalloc(size);
    printf("Success\n");
}
#包括
字符存储器[20000];
结构块{
无符号整数大小;
无整数;
结构块*下一步;
};
结构块*自由列表=(void*)内存;
void initialize(){/
自由列表->大小=20000-sizeof(结构块);
自由列表->自由=1;
自由列表->下一步=空;
}
空分割(结构块*装配槽,无符号整数大小){
结构块*new=(void*)(装配槽+尺寸+尺寸(结构块));
unsigned int temp=(fitting_slot->size)-size-sizeof(结构块);
printf(“剩余内存大小为%d\n”,临时);
new->size=temp;//这就是程序崩溃的地方
新建->免费=1;
新建->下一步=安装槽->下一步;
配件槽->尺寸=尺寸;
配件槽->自由=0;
安装槽->下一步=新建;
}
void*MyMalloc(无符号整数noOfBytes){
结构块*curr;
无效*结果;
如果(!(自由列表->大小)){
初始化();
}
curr=自由列表;
而(((curr->size)<(noOfBytes+sizeof(struct block)))| |((curr->free)==0))&&(curr->next!=NULL)){
当前=当前->下一步;
}
printf(“从大小为%d\n的可用内存中”,curr->size);
printf(“我们将占用此大小:%d\n”,noOfBytes+sizeof(结构块));
如果((当前->大小)=(noOfBytes+sizeof(结构块))){
当前->自由=0;
结果=(无效*)(++curr);
printf(“已分配的精确配件块\n\n”);
}
如果((当前->大小)>(noOfBytes+sizeof(结构块)),则为else{
拆分(当前,无字节);
结果=(无效*)(++curr);
printf(“分配了拆分的配件块\n\n”);
}
否则{
结果=空;
printf(“对不起,没有足够的内存来分配\n\n”);
}
返回结果;
}
int main(){
无符号整数大小=2270*sizeof(字符);
char*k=(char)MyMalloc(大小);
printf(“成功”\n);
}
如果“大小”的数量为2269或更低,则程序工作正常

如果main中的“size”数为2270或更高,则程序将在该行崩溃
new->size=temp
函数中的
split()
表示“引发异常:写入访问冲突”。

我使用了我的调试器。我假设您在split函数中忘记了malloc

struct block* new = (void*)malloc(fitting_slot + size + sizeof(struct block));
如果您使用debbuger,您会发现new->size是无法访问的地址


**如果包含在第1行,这将是第20行。

好的,所以我认为您用了错误的金额进行抵消。C中的指针指示它们所指向的对象的大小,因此如果需要字节偏移量,则需要将指针强制转换为
char*
,或者我认为
void*
也可以正常工作。(见下面的编辑,这是错误的)

我还没有做过详细的调试,但是将第20行从

struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
致:

似乎至少停止了错误

我可以把尺码调整到19968(最大),看起来一切都很好


编辑

因此,作为@R。。下面正确指出,不允许在
void
指针上使用算术运算(尽管
gcc
和其他编译器可能允许您使用它)-例如,请参阅本主题

最合适的方法似乎是对char*进行强制转换。假设fitting_slot变量也已经以块大小为单位,而不是添加
sizeof(struct block)
更简单的方法是只添加1,然后将大小写一次添加到char:

struct block* new = (void*)((char*)(fitting_slot+1) + size);

我已经对此进行了测试,它在gcc中的工作方式似乎与以前的编辑方式相同,但现在合法了。

在结构块*上执行新的is分配指针算法的行中。 当您对类型化指针执行pinter算法时,c语义假定正在操纵数组。例如,结构块*上的ptr++将指针的值增加sizeof(结构块)。
在以这种方式对其执行算术之前,应该将指针强制转换为char*。我不确定我得到了一切,但我希望这能让你开始真的吗?没有来自编译器的警告@AnttiHaapala我当然收到了来自
gcc
的警告,在
void initialise(){
行上也有一个错误,有一个杂散的
/
。现在尝试调试其余部分…我得到了一个不同的错误阈值-适用于2135,而不是2136。编译时,始终启用警告,然后修复这些警告。(对于
gcc
,至少使用:
-Wall-Wextra-Wconversion-pedantic-std=gnu11
)注意:其他编译器使用不同的选项来生成相同的结果我不这么认为-他正在尝试在声明的数组中执行自己的alloc,而fitting_slot是指向当前插槽的指针,因此这(应该)只是在数组中进行偏移。然而,同样明显的是,这里出现了错误……他在哪里尝试分配他希望使用的内存?第3行。
char memory[20000]
是的,你可能是对的,做得很好!无效指针上的算术是无效的。@R..啊,好吧,这就是我有点生疏的地方。所以只要查一下它,事实上,当gcc让你逍遥法外的时候,你不应该这么做……我会考虑如何重构。
(char*)
并回溯t
struct block* new = (void*)((char*)(fitting_slot+1) + size);