Ошибка Malloc: неверная контрольная сумма для освобожденного объекта - PullRequest
9 голосов
/ 24 октября 2008

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

Я не вижу, чтобы отследить его до шаблона или чего-то еще, кроме того, что оно соответствует.

Например, если я назову свою программу как «tail -24 test.in», я получу неверную ошибку контрольной суммы в одной строке при нескольких запусках. Однако с разными файлами и даже разным количеством строк для печати я вернусь без ошибок.

Есть идеи, как отследить проблему, я пытался отлаживать ее часами, но безрезультатно.

Вот код нарушения:

строк определяется как символ ** и был malloc как:

lines = (char**) malloc(nlines * sizeof(char *));

void insert_line(char *s, int len){

  printf("\t\tLine Number: %d Putting a %d line into slot: %d\n",processed,len,slot);
  if(processed > numlines -1){//clean up
    free(*(lines+slot));
    *(lines + slot) = NULL;
  }
  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);
  slot = ++processed % numlines;
}

Ответы [ 6 ]

7 голосов
/ 24 октября 2008

Ваша процедура пишет за пределами выделенного буфера строки.

Размер строки, передаваемой в качестве аргумента (то есть "len"), вероятно, не включает терминатор NUL. Когда вы вызываете malloc для копирования строки (то есть "s"), вам нужно выделить дополнительный байт для ограничителя строки:

 *(lines + slot) = (char *) malloc((len + 1) * sizeof(char));
3 голосов
/ 24 октября 2008

Если вы можете последовательно воспроизвести проблему с конкретными входными параметрами, вы должны выполнить отладку следующим образом:

  • Первая отладка на полную версию, которая вызывает проблему.
  • Затем выясните, когда память, которая собирается быть свободной, была распределена по памяти.
  • Затем выполните отладку в том месте, где используется память malloc.
  • Найдите в окне просмотра памяти выделенный блок памяти. Обратите внимание на начало и конец блока. Вероятно, существует специальное значение, называемое защитный блок непосредственно перед и сразу после блока.
  • Теперь перебирайте код, пока память не освободится. В какой-то момент ваш код должен по ошибке перезаписать защитный блок. Это оскорбительное заявление.

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

1 голос
/ 24 октября 2008

Мой первый вопрос: как вы рассчитываете len? Это просто strlen или в нем есть место для терминатора \ 0? Я думаю, что вы, возможно, превышаете свое распределение в своей strcpy. Плохое поведение, как правило, происходит на границах слов и выглядит случайным. Кроме того, убедитесь, что исходные строки имеют нулевое завершение. Если вы допустили ошибку на стороне чтения и не прекратили их. Тогда strcpy может случайным образом перезаписывать вещи.

  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);

Возможно, попробуйте:

  lines[slot] = (char *) malloc((len + 1) * sizeof(char));
  if(lines[slot] == NULL) exit(EXIT_FAILURE);
  if(strlen(s) <= len){
    strcpy(lines[slot],s);
  }
  else{
    /* do something else... */
  }

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

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

free(lines[slot]);
lines[slot] = NULL;

вместо

free(*(lines+slot));
*(lines + slot) = NULL;

Я бы также посоветовал вам использовать меньше статики. Достаточно легко пройти через них в структуре данных и передать их в ваши аксессоры и мутаторы. Становится намного яснее, где происходит действие, мешающее вам делать такие вещи, как:

static int numlines = 0;
void insert_line(char *s, int len){
    int numlines = 5;

, где вы можете ввести проблемы с областями видимости, которые просто не подходят для отладки.

0 голосов
/ 24 октября 2008

Я согласен с подозрением Римо об этих двух строках, но не касательно того, на что ушёл Римо. Мы должны поделиться ссылкой на поиск этой ошибки.

*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die
0 голосов
/ 24 октября 2008

Я не уверен, что это связано, но эти две строки кажутся мне подозрительными:

  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if((lines + slot) == NULL) exit(EXIT_FAILURE);

Сначала вы присваиваете возврат malloc на lines[slot], а затем проверяете (lines+slot), если последний был NULL, вы разыменовывали указатель NULL!

Также, если lines [slot] (ваш * (lines + slot)) не равен нулю, вы потеряете память, когда назначите ей результат malloc ().

Я предполагаю, что lines это char* строк [] `, а слот находится в пределах допустимой границы!

0 голосов
/ 24 октября 2008

Имеют ли одинаковые значения nlines и numlines?

Позволяет ли вызывающий объект insert_line оставить место для конечного NUL при передаче длины во втором параметре?

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