Странные изменения в программе при использовании free () - PullRequest
1 голос
/ 09 декабря 2010

Я немного запутался.

Я пишу очень простую файловую систему, которая в основном:
-читает в блок данных из файла
-получает хеш из этогоblock
- поиск связанного списка для этого хэша
- если не найдено, добавить
- если найдено, ничего не делать

Проблема:
Когда я не использую free, программа намного медленнее (вероятно, утечка?).

Когда я использую free, программа работает быстрее, заканчивается с размерами блоков 128 и 256, но вылетает при попытке 512 (вылетает при вставке).Я работаю в визуальных студиях, и это просто вылетает.Я получаю сообщение «VS прекратил работать ..», которое не дает никакой информации.

Кроме того, я получаю очень разные результаты, когда использую бесплатное и когда я не использую его.

Любая помощь будет принята с благодарностью.

Хорошо, некоторый код (сокращенно):

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 ]

6 голосов
/ 09 декабря 2010

В вашей функции ins() вы:

  • malloc() памяти и используйте iterator, чтобы указать на нее

  • Несколькооператоры позже вы делаете iterator = head, что означает, что вы потеряли указатель на выделенную область памяти и имеете большую утечку памяти

  • Затем несколько операторов после этого вы делаете / не делаете (в зависимости от комментария) free() элемент, на который указывает итератор, пока он все еще в вашем списке, в то время как вы, вероятно, хотели освободить область от malloc()

EDIT:

Почему вы выделяете память для итератора?Обычно итераторы списка - это простые указатели, которые просто указывают на любой элемент, который в данный момент проверяется кодом.

РЕДАКТИРОВАТЬ 2:

Сбой, скорее всего, вызван тем, что ваша программа обращается к свободной (и, следовательно, доступной) памятиэто все еще часть вашего списка.

Освобожденная память не обязательно возвращается в систему.В зависимости от того, как работает распределитель кучи, он может быть снова выделен вашей программе через другой вызов malloc().Когда ваша программа снова попытается получить к ней доступ, у нее могут быть данные, отличные от ожидаемых.

Две другие точки:

  • Держите ваши идентификаторы уникальными в пределах одной и той же области видимости.Возможно, это не остановит компилятор, но он обязательно остановит человеческий мозг.Например, у вас не должно быть функции ins() с параметром ins.

  • В Visual Studio есть отладчик, который (как мне сказали) довольно хорош.Изучение его использования поможет вам лот .

0 голосов
/ 09 декабря 2010

Также, почему вы делаете:

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

Но ваша версия длиннее и вероятность появления ошибок позже

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...