Invalid Free или коррупция вышла - PullRequest
0 голосов
/ 19 мая 2011

Я новичок в C и полностью потерян из-за этой проблемы.Это домашнее задание для реализации чего-то вроде алгоритма PageRank в C.

Я пытаюсь записать ссылки с других страниц с помощью массива указателей 2D-указателей.Моя программа работает очень хорошо и успешно рассчитывает PageRank для больших наборов ссылок, однако всякий раз, когда я пытаюсь освободить свой массив ссылок, я получаю ошибку «недопустимо свободна».

пример кода:

struct webpage {
  char name[20];
  int links_out;
  struct webpage **links_in; //to hold pointers to pages.
  int index; //stores the position in the pre-sorted array
             // as I have to print it out in this order
};

static struct webpage *pages = NULL;

Это моя структура данных.После прочтения некоторых основных переменных, таких как количество страниц (npages), я затем выделяю память

pages = (struct webpage *)calloc(npages, sizeof(struct webpage));

. Когда я читаю на каждой веб-странице, я выделяю внутренний 2d массив links_in следующим образом

pages[counter].links_in = (struct webpage **)calloc(npages, sizeof(struct webpage *));

а затем каждая страница внутри:

for(i =0; i< npages; ++i)
pages[counter].link_in[i] = (struct webpage *)calloc(1, sizeof(struct webpage));

Я сортирую свой массив веб-страниц.Затем прочитайте информацию о ссылке и выполните бинарный поиск в моем массиве с помощью bsearch, чтобы получить указатель на каждую нужную страницу.

struct webpage *temp_in;
struct webpage *temp_out;

temp_in = bsearch(temp_str, pages, npages, sizeof(struct webpage), struct_cmp_by_name);
temp_out = bsearch(temp_str2, pages, npages, sizeof(struct webpage), struct_cmp_by_name);

Затем я назначаю

temp_in->links_in[temp_out->index] = temp_out;

Все это прекрасно работает, и я могу получить доступ ко всем нужным данным для расчета PageRank.Как только я закончу, я пытаюсь освободить память следующим образом:

for(int i = 0; i < npages; ++i){
  for(int k = 0; k < npages; ++k){
     if(pages[i].links_in[k] != NULL){
          free(pages[i].links_in[k]); //this line is causing the error
          pages[i].links_in[k] = NULL;
     }
  }
 free(pages[i].links_in);
}

При вызове free внутри цикла k выдается недопустимая ошибка free (или двойное освобождение от коррупции) при самом первом вызове..

Я перебрал код с помощью gdb, и, похоже, все указывает на правильную вещь.GDB перечисляет эту строку как точку, где программа прерывается.

valgrind говорит примерно то же самое:

Invalid free() / delete / delete[]
at 0x4A05187: free (vg_replace_malloc.c:325)
by 0x4009C4: memory_dump (pagerank.c: 87)  // this is the line free(pages[i].links_in[k];
by 0x4013F2: seq_check_condition (pagerank.c:355)
by 0x40162F: main (pagerank.c:418)

Ни при каких обстоятельствах я не удаляю / не освобождаю эту (или любую другую память) доэтот момент.

спасибо за любые предложения.

Ответы [ 3 ]

1 голос
/ 19 мая 2011

Полагаю, это проблема:

temp_in->links_in[temp_out->index] = temp_out;

Кажется, вы уже выделили память для всех ваших указателей 'links_in' - затем вы меняете этот указатель так, чтобы он указывал на другой бит памятиВы выделили.

Может быть, вы хотите что-то вроде:

memcpy(temp_in->links_in[temp_out->index], temp_out, sizeof(struct webpage));

... или что-то вроде редизайна?

0 голосов
/ 19 мая 2011

Я думаю, вам не нужно делать следующее

for(i =0; i< npages; ++i)
    pages[counter].link_in[i] = (struct webpage *)calloc(1, sizeof(struct webpage));

Это потому, что для каждой страницы вы выделяете новый указатель webpage. pages[counter].link_in[i] используется для удержания указателя на webpage, т.е. он должен указывать на уже существующую и выделенную страницу. Таким образом, вам нужно только назначить адрес этого webpage экземпляра.

Я думаю, что проблема здесь:

Измените этот код:

for(int i = 0; i < npages; ++i){
  for(int k = 0; k < npages; ++k){
     if(pages[i].links_in[k] != NULL){
          free(pages[i].links_in[k]); //this line is causing the error
          pages[i].links_in[k] = NULL;
     }
  }
 free(pages[i].links_in);
}

К этому:

for(int i = 0; i < npages; ++i){
   free (pages[i].links_in);
}
free (pages);

Это связано с тем, что ссылки, которые удерживает pages[i].links_in[x], являются указателями на некоторые pages[j], а также потому, что конкретный адрес pages[j] может встречаться в pages[i].links_in[x] для любого числа i, поэтому потенциально адрес pages[j] встречается в нескольких местах, который пытается освободить ваша подпрограмма в строке free(pages[i].links_in[k]);.

Пожалуйста, дайте нам знать, если это поможет.

0 голосов
/ 19 мая 2011

Похоже, pages[i].links_in[k] должно быть pages[i].link_in[k].

...