开发者

Weird change in program when using free()

I'm a bit confused.

I'm writing a very simple file system that basically:

-reads in a block of data from a file

-gets a hash from that block

-search a linked-list for that hash

-if not found, append

-if found, do nothing

The problem:

When I don't use free, the program is a lot slower (probably leaking?).

When I use free, the program runs faster, finishes with block sizes of 128 and 256, but crashes when I try 512 (crashes in insert). I'm working in visual studios, and it just crashes. I get the "VS stopped working.." message which provides no insight.

On top of that, I get much different results when I use free vs. when I don't use it.

Any help would be very much appreciated.

开发者_如何学运维

Okay, some code (abbreviated):

struct list_el
{
    char* hash;
    struct list_el* next;
    struct list_el* prev;
};  
typedef struct list_el item;

item* head, *tail;

void ins(item* ins) 
{
item* iterator = (item*)malloc(sizeof(item));
if(iterator == NULL)
{
    printf("out of memory\n");
    exit(1);
}
else if(head != NULL)
{
    iterator = head;
    while(iterator != NULL)
    {
        if(strcmp(iterator->hash, ins->hash) == 0)
        {
            //free(iterator); (problem line)
            matches++;
            return;
        }
        else if(iterator->next != NULL)
            iterator = iterator->next;
        else
            break;

    }
}

unique_blocks++;
if(head == NULL) 
{
    head = ins;
    ins->prev = NULL;

}

else 
{
    tail->next = ins;
    ins->prev = tail;
}

tail = ins;
ins->next = NULL;
}


int main()
{
unsigned char* c = (unsigned char*)malloc(BLOCKSIZE+1);
if(c == NULL)
    exit(1);
FILE* fp = fopen("input2","r");
if(fp == NULL)
    exit(1);
int i = 0;

char* answer = (char*)malloc(sizeof(char)*90);
if(answer == NULL)
    exit(1);
item* ins_item;
char ch;
do
{
    if(i == BLOCKSIZE)
    {       
        i = 0;
        answer = sha1((unsigned char*)c);
        ins_item = (item*)malloc(sizeof(item));
        if(ins_item == NULL)
            exit(1);
        ins_item->hash = answer;
        ins(ins_item);

    }
    else
    {
        ch = fgetc(fp);
        bytes_read++;
        c[i] = ch;
        i++;
    }
}while(ch != EOF);
fclose(fp);
return 0;
}


In your ins() function you:

  • malloc() memory and use iterator to point to it

  • A few statements later you do iterator = head, which means that you lost the pointer to the allocated memory area and have a major memory leak

  • Then a few statement after that you do/do not (depending on the comment) free() the item pointed to by the iterator while it is still in your list, while you probably wanted to free the area from malloc()

EDIT:

Why do you allocate memory for the iterator? Usually list iterators are simple pointers that just point to whatever item the code is currently examining.

EDIT 2:

The crash is most probably caused by your program accessing freed (and thus anavailable) memory that is still part of your list.

Freed memory is not necessarily returned to the system. Depending on how the heap allocator works it could even be allocated again to your program via another malloc() call. When your program tries to access it again it could have very different data than expected.

Two other points:

  • Keep your identifiers unique within the same scope. It may not make the compiler stop, but it sure makes the human brain stop. E.g. you should not have an ins() function with an ins parameter.

  • Visual Studio has a debugger that (I'm told) is quite good. Learning how to use it would help you a lot.


Also why do you do:

while(iterator != NULL)
{
    if(strcmp(iterator->hash, ins->hash) == 0)
    {
        //free(iterator); (problem line)
        matches++;
        return;
    }
    else if(iterator->next != NULL)
        iterator = iterator->next;
    else
        break;

}

This is functionally equivalent to:

while(iterator != NULL)
{
    if(strcmp(iterator->hash, ins->hash) == 0)
    {
        //free(iterator); (problem line)
        matches++;
        return;
    }

    iterator = iterator->next;
}

But your version is longer and more likely to develop errors later.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜