malloc.c:3096: sYSMALLOc: Assertion <километр непарсенного выражения> failed. (Хоть бы NULL возвращал)

Модератор: Модераторы разделов

nick87720z
Сообщения: 180
ОС: Gentoo / Calculate

malloc.c:3096: sYSMALLOc: Assertion <километр непарсенного выражения> failed.

Сообщение nick87720z »

После данного сообщения происходит "Аварийный останов" (Aborted)

Насколько я понял, эта ошибка - не редкость.
http://www.nigma.ru/?s=malloc.c%3A3096%3A+...;t=web&sf=1
https://bugzilla.redhat.com/show_bug.cgi?id=585689
https://bugs.launchpad.net/ubuntu/+source/i...ync/+bug/541980

Что это значит, так и не понял.

Вот еще нашел ссылку:
http://bytes.com/topic/c/answers/887963-allocate-memory-heap

Там говорится о множественном освобождении, но я не понял, где там его увидели.

Вот проблемный код, ошибка происходит на первом malloc()
Ошибка происходит после очередного вызова procfs_get_process_file(), если не освобождать ее результат.
Если освобождать, количнство успешных вызовов увеличивается где-то в 1,5 раза, но происходит "Double free or corruption".

Работа не моя - просто я вовлечен в этот проект.

Код: Выделить всё

#define BUFFER_SIZE 4096

static char g_buffer[BUFFER_SIZE];

bool
procfs_get_process_file(
  unsigned long long pid,
  const char * filename,
  char ** buffer_ptr_ptr,
  size_t * size_ptr)
{
  printf("\\ procfs_get_process_file\n");
  int fd;
  ssize_t ret;
  size_t max;
  char * buffer_ptr;
  char * read_ptr;
  size_t buffer_size;
  size_t used_size;

  sprintf(g_buffer, "/proc/%llu/%s", pid, filename);

  printf("Get file descriptor\n");
  fd = open(g_buffer, O_RDONLY);
  if (fd == -1)
  {
    return false;
  }

  buffer_size = BUFFER_SIZE;
  printf("Allocate buffer with size %u\n", (unsigned)buffer_size);
  buffer_ptr = malloc(buffer_size);
  printf("Checking, wether it is allocated\n");
  if (buffer_ptr == NULL)
  {
    log_error("malloc failed to allocate buffer with size %zu", buffer_size);
    return false;
  }

  unsigned iteration = 0;

  used_size = 0;
  read_ptr = buffer_ptr;
loop:
  printf("procfs_get_process_file: loop: iteration = %u\n", iteration++);
  max = buffer_size - used_size;
  if (max < BUFFER_SIZE / 4)
  {
    buffer_size = used_size + BUFFER_SIZE;
    read_ptr = realloc(buffer_ptr, buffer_size);
    if (read_ptr == NULL)
    {
      log_error("realloc failed to allocate buffer with size %zu", buffer_size);
      free(buffer_ptr);
      close(fd);
      return false;
    }

    buffer_ptr = read_ptr;
    read_ptr = buffer_ptr + used_size;
    max = BUFFER_SIZE;
  }

  ret = read(fd, read_ptr, max);
  if (ret > 0)
  {
    ASSERT(ret <= max);
    read_ptr += ret;
    used_size += ret;
    ASSERT(used_size <= buffer_size);
    goto loop;
  }

  close(fd);

  if (ret < 0)
  {
    ASSERT(ret == -1);
    close(fd);
    return false;
  }

  if (used_size == buffer_size)
  {
    buffer_ptr = realloc(buffer_ptr, buffer_size + 1);
    if (buffer_ptr == NULL)
    {
      log_error("realloc failed to allocate buffer with size %zu", buffer_size + 1);
      free(buffer_ptr);
      return false;
    }
  }

  buffer_ptr[buffer_size] = 0;

  *buffer_ptr_ptr = buffer_ptr;
  *size_ptr = used_size;

  printf("/ procfs_get_process_file\n");
  return true;
}
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: malloc.c:3096: sYSMALLOc: Assertion <километр непарсенного выражения> failed.

Сообщение Nazyvaemykh »

buffer_ptr[buffer_size] = 0;

вот эта строчка (6 снизу, если не считать пустых) — она точно правильная?
Что-то мне подсказывает, что если строчка
buffer_ptr = realloc(buffer_ptr, buffer_size + 1); (14-я снизу)
не выполняется, то там происходит запись за пределы, что не очень хорошо.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
nick87720z
Сообщения: 180
ОС: Gentoo / Calculate

Re: malloc.c:3096: sYSMALLOc: Assertion <километр непарсенного выражения> failed.

Сообщение nick87720z »

Сегодня нашел одну закономерность. С procfs_get_process_file() все впорядке. Ее можно использовать аж 10000 раз (проверял в цикле) над одним и тем же файлом. Однако, если читать разные файлы (например "maps" из "/proc/[pid]" с разным значением pid ), на ~190 с файле происходид тот самый "Double free or corruption".

Такое ощущение, что я что-то упустил - может, поверку.

P.S. В следующий раз буду выкладывать в nopaste. А то совсем монотонно.
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: malloc.c:3096: sYSMALLOc: Assertion <километр непарсенного выражения> failed.

Сообщение Nazyvaemykh »

Кроме той ошибки, что я уже отметил, других не вижу. Последовательное выполнение строчек:

Код: Выделить всё

read_ptr = realloc(buffer_ptr, buffer_size);
…
buffer_ptr = read_ptr;
…
buffer_ptr[buffer_size] = 0;

Функция realloc выделила buffer_size байтов, а запись идет в (buffer_size+1)-ый байт, что чревато разрушением кучи.

Так и получилось.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
nick87720z
Сообщения: 180
ОС: Gentoo / Calculate

Re: malloc.c:3096: sYSMALLOc: Assertion <километр непарсенного выражения> failed.

Сообщение nick87720z »

Дал ссылку на тред автору. Он сначала думал, что это моя работа :D Нашел несколько багов.
В общем, спасибо.
Спасибо сказали: