C 由于奇怪的未知原因导致的分段错误

C 由于奇怪的未知原因导致的分段错误,c,unix,malloc,sbrk,C,Unix,Malloc,Sbrk,在下面的代码和平中(我正在实现malloc(),free()和realloc()),我得到了一个分段错误(内核转储): 现在,假设它将打印aaa或bbb,它只是在执行第X行中的printf()后立即宣布一个分段错误。如果我键入“printf(“a”)而不是当前的printf(),它将根本不会打印“a”。真奇怪。 它打印: curr is 0x86be000 and ptr is 0x86be000 然而,它会立即退出并抛出一个分段错误。 变量head是该文件中的静态变量。我真的很想知道问题出在

在下面的代码和平中(我正在实现
malloc()
free()
realloc()
),我得到了一个
分段错误(内核转储)

现在,假设它将打印
aaa
bbb
,它只是在执行第X行中的
printf()
后立即宣布一个分段错误。如果我键入“printf(“a”)而不是当前的
printf()
,它将根本不会打印“a”。真奇怪。 它打印:

curr is 0x86be000 and ptr is 0x86be000
然而,它会立即退出并抛出一个分段错误。 变量
head
是该文件中的静态变量。我真的很想知道问题出在哪里,真的很奇怪。下面是头文件中的语句:

void free(void* ptr);
这么简单,你觉得这里有什么问题吗? 完整的代码是可用的,但我怀疑它的相关,该程序应该,至少,打印“aaa”或“bbb”,它不这样做。
有什么想法吗?我真的很绝望。

下面的代码符合警告,但执行得非常完美

#include <unistd.h>
typedef struct metadata_block* p_block;

typedef struct metadata_block
{
        size_t size;
        p_block next;
        int free;
}metadata_block;

void* malloc(size_t size);
void free(void* ptr);
void* realloc(void* ptr, size_t size);

//THE MAIN CODE IS AT THE BOTTOM//
#include <stdio.h>

static p_block head = NULL;

void* malloc(size_t size)
{
        void* ptr;
        int isOk = 1;
        int temp = 0;
        p_block curr = head;
        if(size <= 0)
        {
                return NULL;
        }
        if(curr)
        {
                while(curr->next && isOk)
                {
                        if(curr->free && size <= curr->size)
                        {
                                isOk = 0;
                        }

                        if(isOk)
                        {
                                curr = curr->next;
                        }
                }

                if(isOk) //what will happen if there isn't one free and big enough
                {
                        ptr = sbrk(size + sizeof(metadata_block));
                        if((int)ptr <= 0)
                                return NULL;
                        ((p_block)(ptr))->size = size;
                        ((p_block)(ptr))->next = NULL; //next run it's the real next.
                        ((p_block)(ptr))->free = 0;

                        return (ptr + sizeof(metadata_block));
                }
                else
                {
                        if(curr->next)
                        {
                                ptr = curr;
                                if(curr->size == size || size > (curr->size - sizeof(metadata_block) - 1)) //not enough room for another block of memory
                                {
                                        ((p_block)(ptr))->free = 0;
                                        return (ptr + sizeof(metadata_block));
                                }

                                temp = curr->size;
                                ((p_block)(ptr))->size = size;
                                ((p_block)(ptr))->free = 0;
                                ((p_block)(ptr + sizeof(metadata_block) + size))->next = curr->next;
                                ((p_block)(ptr))->next = ptr + sizeof(metadata_block) + size;
                                ((p_block)(ptr + sizeof(metadata_block) + size))->size = temp - size;
                                ((p_block)(ptr + sizeof(metadata_block) + size))->free = 1;

                                return (ptr + sizeof(metadata_block));
                        }
                        else
                        {
                                ptr = curr;
                                if((int)sbrk(size - curr->size) > 0)
                                {
                                        ((p_block)(ptr))->size = size;
                                        ((p_block)(ptr))->next = NULL; //next run it's the real next.
                                        ((p_block)(ptr))->free = 0;

                                        return (ptr + sizeof(metadata_block));
                                }
                                return NULL;
                        }
                }
        }
        else
        {
                ptr = sbrk(size + sizeof(metadata_block));
                if((int)ptr <= 0)
                        return NULL;
                head = ptr;
                ((p_block)(ptr))->size = size;
                ((p_block)(ptr))->next = NULL;
                ((p_block)(ptr))->free = 0;
        }


        return ptr;
}

void free(void* ptr)
{
        void* curr = head;
        void* before = NULL;
        int isLegal = 0;
        printf("curr is %p and ptr is %p\n", curr, ptr);
        if(curr == ptr)
        {
                printf("aaa\n");
        }
        else
        {
                printf("bbb\n");
        }
        if(curr && ptr)
        {
                while(curr && !isLegal)
                {
                        if(((p_block)(ptr)) == ((p_block)(curr))->next)
                        {
                                before = curr;
                                isLegal = 1;
                                curr = ((p_block)(curr))->next;
                        }
                        else
                        {
                                curr = ((p_block)(curr))->next;
                        }
                }

                if(isLegal)
                {
                        curr = curr - sizeof(metadata_block);

                        if(((p_block)(curr))->next)
                        {
                                ((p_block)(curr))->free = 1;
                        }
                        else
                        {
                                sbrk(0-(((p_block)(curr))->size + sizeof(metadata_block)));
                                ((p_block)(before))->next = NULL;
                        }
                }
        }
}

void* realloc(void* ptr, size_t size)
{
        void* ptr2 = malloc(size);
        int i;
        for(i = 0 ; i < size ; i++)
        {
                *((char*)(ptr2 + i)) = *((char*)(ptr + i));
        }

        free(ptr);

        return ptr2;
}


int main()
{
        printf("I'm in.\n");
        char * str = malloc(10);
        printf("After Malloc()\n");
        void * ptr = (void *) str;
        void * ptr2;
        if(!str)
        {
                printf("Fail.\n");
        }
        strcpy(str,"TEST!\0");
        printf("About to free\n");
        free(str);
        printf("free: OK!\n");
}

注意-在同一文件中安装mm.h include I include code

,因为您没有打印换行符或使用
fflush
,所以您的printf输出没有刷新。如果您正在调试打印语句,则应该在每个打印语句上使用换行符。@JS1我不明白,您基本上是说我应该添加一个“\n”或使用“fflush(stdout)”?不使用任何一个。因此,在您更改
aaa
bbb
以添加换行符后,您在输出中看不到任何一个换行符,但仍然可以看到以前的printf输出?我不是说它会修复你的segv,只是你应该看到
aaa
bbb
。segv可能会在稍后发生。@JS1哦,在“aaa”和“bbb”中添加“\n”,是的,它正在工作!非常感谢你!那么,您抱怨seg故障的原因是什么?事实上,在添加“\n”之后,它起了作用。谢谢,我不知道在unix中它有那么重要,这是一个很好的工作。但是,如果您能够说明OP代码中存在的问题以及您为解决这些问题所做的更改,这将对未来的访问者非常有帮助。谢谢。:-)
#include <unistd.h>
typedef struct metadata_block* p_block;

typedef struct metadata_block
{
        size_t size;
        p_block next;
        int free;
}metadata_block;

void* malloc(size_t size);
void free(void* ptr);
void* realloc(void* ptr, size_t size);

//THE MAIN CODE IS AT THE BOTTOM//
#include <stdio.h>

static p_block head = NULL;

void* malloc(size_t size)
{
        void* ptr;
        int isOk = 1;
        int temp = 0;
        p_block curr = head;
        if(size <= 0)
        {
                return NULL;
        }
        if(curr)
        {
                while(curr->next && isOk)
                {
                        if(curr->free && size <= curr->size)
                        {
                                isOk = 0;
                        }

                        if(isOk)
                        {
                                curr = curr->next;
                        }
                }

                if(isOk) //what will happen if there isn't one free and big enough
                {
                        ptr = sbrk(size + sizeof(metadata_block));
                        if((int)ptr <= 0)
                                return NULL;
                        ((p_block)(ptr))->size = size;
                        ((p_block)(ptr))->next = NULL; //next run it's the real next.
                        ((p_block)(ptr))->free = 0;

                        return (ptr + sizeof(metadata_block));
                }
                else
                {
                        if(curr->next)
                        {
                                ptr = curr;
                                if(curr->size == size || size > (curr->size - sizeof(metadata_block) - 1)) //not enough room for another block of memory
                                {
                                        ((p_block)(ptr))->free = 0;
                                        return (ptr + sizeof(metadata_block));
                                }

                                temp = curr->size;
                                ((p_block)(ptr))->size = size;
                                ((p_block)(ptr))->free = 0;
                                ((p_block)(ptr + sizeof(metadata_block) + size))->next = curr->next;
                                ((p_block)(ptr))->next = ptr + sizeof(metadata_block) + size;
                                ((p_block)(ptr + sizeof(metadata_block) + size))->size = temp - size;
                                ((p_block)(ptr + sizeof(metadata_block) + size))->free = 1;

                                return (ptr + sizeof(metadata_block));
                        }
                        else
                        {
                                ptr = curr;
                                if((int)sbrk(size - curr->size) > 0)
                                {
                                        ((p_block)(ptr))->size = size;
                                        ((p_block)(ptr))->next = NULL; //next run it's the real next.
                                        ((p_block)(ptr))->free = 0;

                                        return (ptr + sizeof(metadata_block));
                                }
                                return NULL;
                        }
                }
        }
        else
        {
                ptr = sbrk(size + sizeof(metadata_block));
                if((int)ptr <= 0)
                        return NULL;
                head = ptr;
                ((p_block)(ptr))->size = size;
                ((p_block)(ptr))->next = NULL;
                ((p_block)(ptr))->free = 0;
        }


        return ptr;
}

void free(void* ptr)
{
        void* curr = head;
        void* before = NULL;
        int isLegal = 0;
        printf("curr is %p and ptr is %p\n", curr, ptr);
        if(curr == ptr)
        {
                printf("aaa\n");
        }
        else
        {
                printf("bbb\n");
        }
        if(curr && ptr)
        {
                while(curr && !isLegal)
                {
                        if(((p_block)(ptr)) == ((p_block)(curr))->next)
                        {
                                before = curr;
                                isLegal = 1;
                                curr = ((p_block)(curr))->next;
                        }
                        else
                        {
                                curr = ((p_block)(curr))->next;
                        }
                }

                if(isLegal)
                {
                        curr = curr - sizeof(metadata_block);

                        if(((p_block)(curr))->next)
                        {
                                ((p_block)(curr))->free = 1;
                        }
                        else
                        {
                                sbrk(0-(((p_block)(curr))->size + sizeof(metadata_block)));
                                ((p_block)(before))->next = NULL;
                        }
                }
        }
}

void* realloc(void* ptr, size_t size)
{
        void* ptr2 = malloc(size);
        int i;
        for(i = 0 ; i < size ; i++)
        {
                *((char*)(ptr2 + i)) = *((char*)(ptr + i));
        }

        free(ptr);

        return ptr2;
}


int main()
{
        printf("I'm in.\n");
        char * str = malloc(10);
        printf("After Malloc()\n");
        void * ptr = (void *) str;
        void * ptr2;
        if(!str)
        {
                printf("Fail.\n");
        }
        strcpy(str,"TEST!\0");
        printf("About to free\n");
        free(str);
        printf("free: OK!\n");
}
I'm in.                                                   
After Malloc()                                            
About to free                                             
curr is 0x1049000 and ptr is 0x1049000                    
aaafree: OK!