*** Обнаружен glibc *** free(): неверный следующий размер (быстрый) должен работать?

Я работаю над существующим проектом c (spglib на sourceforge) и столкнулся со следующей проблемой после очистки некоторых инициализаций массива:

* glibc обнаружен * тесты/spglibtest: free(): неверный следующий размер (быстро): 0x08ab46e0 ***

Обратная трасса:

#0  0xb7fe1424 in __kernel_vsyscall ()
#1  0xb5cfdd61 in raise () from /lib/libc.so.6
#2  0xb5cff5ee in abort () from /lib/libc.so.6
#3  0xb5d397ed in ?? () from /lib/libc.so.6
#4  0xb5d3f7b1 in ?? () from /lib/libc.so.6
#5  0xb5d4052b in ?? () from /lib/libc.so.6
#6  0xb5d441cd in free () from /lib/libc.so.6
#7  0xb6681484 in sym_get_multiplicity (cell=0xbfffe1f0, symprec=0.050000000000000003) at /git/xtalopt-public/src/spglib/symmetry.c:168
#8  0xb6680550 in spg_find_primitive (lattice=0xbfffe2a8, position=0x813c6f0, types=0x813c700, num_atom=2, symprec=0.050000000000000003)
    at /git/xtalopt-public/src/spglib/spglib.c:253

Ошибка находится в строке «free (trans)» ниже:

int sym_get_multiplicity(const Cell *cell, const double symprec)
{
  int i, rc;
  double **trans;
  trans = (double**)malloc(cell->size * sizeof(double*));
  for (i = 0; i < cell->size; i++) {
    trans[i] = (double*)malloc(3 * sizeof(double));
  }

  rc = get_translation(&trans[0][0], identity, cell, symprec);

  for (i = 0; i < cell->size; i++) {
    free(trans[i]);
  }
  free(trans);

  return rc;
}

get_translation присваивает значения трансу следующим образом:

static int get_translation(double trans[][3], const int rot[3][3], const Cell *cell,
                           const double symprec)
{
...
  for (j = 0; j < 3; j++) {
    trans[num_trans][j] = someDouble;
  }
...
}

Valgrind показывает следующее при записи в массив в get_translation:

==17929== Invalid write of size 8
==17929==    at 0x56BE8A7: get_translation (symmetry.c:285)
==17929==    by 0x56BE44B: sym_get_multiplicity (symmetry.c:163)
...
==17929==  Address 0x9cb5868 is 0 bytes after a block of size 8 alloc'd
==17929==    at 0x4024918: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==17929==    by 0x56BE3F7: sym_get_multiplicity (symmetry.c:158)
....

Это наводит меня на мысль, что он пытается писать за пределами выделенной памяти для транса, но пишет в транс[0][0], а транс имеет размерность [2][3]. Это должно сработать, AFAIK, может ли кто-нибудь увидеть что-то, что я упускаю?


person dlonie    schedule 15.09.2010    source источник
comment
Таким образом, хотя это и не ответ, транс не совсем то же самое, что и что-то, что определяется как двойной транс[2][3]. В частности, в вашем примере транс[0][2] и транс[1][0] не размещаются последовательно в памяти, что необходимо для чего-то вроде dobule trans[2][3].   -  person Aurojit Panda    schedule 16.09.2010
comment
Вы должны получить аргумент, передаваемый из предупреждения о несовместимом типе указателя при вызове get_translation() - я предлагаю повысить уровень предупреждения вашего компилятора.   -  person caf    schedule 16.09.2010
comment
Действительно не уверен, почему это было помечено как дубликат. Невероятно общее сообщение об ошибке такое же, но основная проблема совсем другая...   -  person dlonie    schedule 18.07.2014


Ответы (2)


Ваши типы неверны, вы не можете передать указатель на массив указателей функции, ожидающей массив массивов (т.е. указатель на массив).

Для подписи get_translation, которая у вас есть, вам нужно:

double (*trans)[3] = malloc(cell->size * sizeof(double[3]));
person CB Bailey    schedule 15.09.2010
comment
С точки зрения управления памятью это имеет для меня смысл, и это работает, когда я вношу изменения — спасибо! Однако у меня возникли проблемы с пониманием синтаксиса в объявлении, и поиск в Google не нашел много информации об этом. Можете порекомендовать ссылку на эту технику? Еще раз спасибо! - person dlonie; 16.09.2010
comment
@dlonie: Несколько недавних вопросов на эту тему: stackoverflow.com/questions/3707096 и stackoverflow.com/questions/3706704 . - person CB Bailey; 16.09.2010
comment
А, теперь я вижу. Я был сбит с толку, увидев разыменование указателя в его объявлении - довольно неинтуитивно, исходя из моего опыта работы с С++! Совет о правиле спирали помог прояснить это. - person dlonie; 16.09.2010

Итак, вот, пожалуй, одна проблема. Ваша функция, кажется, предполагает (на основе) trans[num_trans][j] = someDouble; этот транс на самом деле представляет собой массив, выложенный последовательно, что, как я уже упоминал выше, в данном случае неверно. Вы выделяете массив указателей, а не двумерный массив. Что-то похожее

двойной * транс = malloc (ячейка-> размер * 3); может быть лучше. В общем, вы можете использовать массив 1d вместо массива 2d и просто использовать его как двумерный массив.

person Aurojit Panda    schedule 15.09.2010