使用free()时程序发生奇怪的变化

时间:2010-12-09 09:54:14

标签: c

我有点困惑。

我正在编写一个非常简单的文件系统,基本上是:
- 从文件中的数据块中读取 - 从该块中获取哈希
- 搜索该哈希的链表 如果没有找到,请附上
- 如果发现,什么都不做

问题:
当我不使用免费时,程序要慢得多(可能是泄漏?)。

当我使用free时,程序运行得更快,块大小为128和256,但是当我尝试512(插入时崩溃)时崩溃。我在视觉工作室工作,它只是崩溃了。我得到“VS停止工作......”的消息,没有提供任何见解。

最重要的是,当我使用free和不使用它时,我会得到很多不同的结果。

非常感谢任何帮助。

好的,有些代码(缩写):

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;
}

2 个答案:

答案 0 :(得分:6)

在您的ins()功能中:

  • malloc()内存并使用iterator指向它

  • 稍后您执行iterator = head的一些语句,这意味着您丢失了指向已分配内存区域的指针并且存在重大内存泄漏

  • 然后在你的列表中仍然之后你做/不做(取决于评论)free()迭代器指向的项目,虽然您可能想要从malloc()

  • 中释放该区域

编辑:

为什么要为迭代器分配内存?通常列表迭代器是简单的指针,只指向代码当前正在检查的任何项目。

编辑2:

崩溃很可能是由于您的程序访问了仍然属于列表的已释放(因此也是可用的)内存。

释放的内存不一定会返回给系统。根据堆分配器的工作方式,它甚至可以通过另一个malloc()调用再次分配给您的程序。当您的程序再次尝试访问它时,它可能会有与预期不同的数据。

另外两点:

  • 在同一范围内保持您的标识符唯一性。它可能不会使编译器停止,但它肯定会使人脑停止。例如。您不应该使用带有ins()参数的ins函数。

  • Visual Studio有一个调试器(我被告知)非常好。学习如何使用它可以帮助你很多

答案 1 :(得分:0)

你也为什么这样做:

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;

}

这在功能上等同于:

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

    iterator = iterator->next;
}

但是你的版本更长,更有可能在以后发生错误。