分段错误是一个奇怪的未知原因

时间:2014-12-22 09:51:12

标签: c unix malloc sbrk

我在以下代码安静中获得segmentation fault (core dumped)(我实施malloc()free()realloc()):

void free(void* ptr)
{
     void* curr = head;
     void* before = NULL;
     int isLegal = 0;
     /*Line X*/printf("curr is %p and ptr is %p\n", curr, ptr);
     if(curr == ptr)
     {
         printf("aaa");
     }
     else
     {
         printf("bbb");
     }
     /*Some more code that actually frees the pointer and not relevant here*/
 }

现在,您假设它打印aaabbb,它只是在执行第X行中的printf()后立即宣布细分错误。我输入" printf(" a")"而不是当前的printf(),它不会打印出一个'一点都不这真的很奇怪。 它打印:

curr is 0x86be000 and ptr is 0x86be000

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

void free(void* ptr);

就这么简单,你在这里看到任何问题吗? 完整的代码可用here,但我怀疑它是否相关,该程序至少应打印“aaa'或者' bbb',它没有那样做。 任何的想法?我非常绝望。

1 个答案:

答案 0 :(得分:0)

以下代码编译时带有警告,但确实执行完毕

#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!  

注意 - 而不是你的mm.h包括我在同一个文件中包含的代码