Ошибка Маллока:неверная контрольная сумма для освобожденного объекта

StackOverflow https://stackoverflow.com/questions/232678

  •  04-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

линии определены как char** и были распределены по принципу 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;
}
Это было полезно?

Решение

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

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

 *(lines + slot) = (char *) malloc((len + 1) * sizeof(char));

Другие советы

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

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

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

Мой первый вопрос: как рассчитать 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;

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

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

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

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

  *(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 * lines [] `, а слот находится в пределах допустимой границы!

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

*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top