Что случилось с перемещаемым аллокатором?

Я читал старую документацию glibc здесь, когда увидел три странные функции, которые Я никогда раньше не видел (r_alloc, r_alloc_free и r_re_alloc). Я думаю, они внедрили распределитель, который перераспределяет память для целей дефрагментации, но больше нигде не могу найти больше информации.

Можете ли вы рассказать мне больше об этих функциях? Они все еще в Glibc? Если нет, то почему их убрали?


person Mabus    schedule 09.10.2015    source источник
comment
Как правило, недокументированные функции предназначены для внутреннего использования. Даже если они не удалены пока, они могут быть удалены, переименованы или изменены в любой будущей версии по мере развития внутренней структуры glibc.   -  person MSalters    schedule 09.10.2015
comment
@MSalters Функции не являются ни внутренними, ни недокументированными: вопрос касается функций, найденных в (старой) документации.   -  person Employed Russian    schedule 10.10.2015
comment
Если вы хотите копировать или сжимать сборку мусора, язык C, вероятно, не для вас.   -  person dfeuer    schedule 10.10.2015


Ответы (1)


Можете ли вы рассказать мне больше об этих функциях?

Что вы хотите знать о них? Они довольно четко описаны в руководстве, в котором вы их нашли.

Они чем-то похожи на Win32 LocalAlloc и LocalLock — вы получаете дескриптор объекта памяти, но для получения пригодного для использования адреса этого объекта требуется дополнительный шаг. Как правило, это плохая идея, за исключением систем с очень ограниченным объемом памяти.

Они все еще в Glibc?

No.

Если нет, то почему их убрали?

Потому что они, как правило, плохая идея и размножаются до труднодоступных ошибок.

Обновление:

Какие ошибки возможны при использовании чего-то подобного?

Вот пример:

const char *my_strcat(const char *a, const char *b)
{
  const size_t len_a = strlen(a);
  const size_t len_b = strlen(b);
  char *handle;

  if (r_alloc((void**)&handle, len_a + len_b + 1) == NULL) return NULL;
  memcpy(handle, a, len_a);
  memcpy(handle + len_a, b, len_b + 1);

  return handle;
}

// There are memory leaks here. Ignore them for now.
int main()
{
  const char *result = my_strcat("abc", my_strcat("def", "ghi"));

  return strcmp(result, "abcdefghi");
}

Можете ли вы обнаружить ошибку?

Иногда программа завершается успешно, иногда с ошибкой с ненулевым кодом выхода, а иногда с ошибкой SIGSEGV.

person Employed Russian    schedule 10.10.2015
comment
Я попытался откопать запись в журнале изменений, в которой упоминается удаление, но, похоже, не могу ее найти. Вы знаете, где было объявлено об изменении? - person dfeuer; 10.10.2015
comment
@dfeuer Они не были частью первоначального импорта glibc-2.0. Я предполагаю, что это артефакт glibc-1.x. - person Employed Russian; 10.10.2015
comment
¿Можете ли вы объяснить, почему это плохая идея? ¿Какие ошибки возможны при использовании чего-то подобного? Заранее спасибо. - person Mabus; 10.10.2015
comment
Можете ли вы обнаружить ошибку? Кроме того, что результирующая строка не завершается NUL? Эта ошибка возможна и со стандартным malloc(). ;) - person Andrew Henle; 10.10.2015
comment
@AndrewHenle Строка правильно завершается NUL. Этой ошибки там нет. - person Employed Russian; 10.10.2015
comment
Баг, как я вижу, в том, что дескриптор находится в стеке. В данном случае это не имеет значения: поскольку вы не вызываете какую-либо функцию выделения памяти, указатель не может быть перемещен. Но в более сложном сценарии это может привести к катастрофе. Однако я думаю, что при аккуратном программировании можно избежать проблем, как и в обычном коде на C. Но я не уверен, что дефрагментация по-прежнему актуальна на современных ПК, поэтому пока не буду пытаться использовать что-то подобное :-). - person Mabus; 10.10.2015
comment
@Mabus Нет, вы еще не нашли ошибку. Обратите внимание, что есть два вызова r_alloc, и подумайте, что второй вызов может сделать с памятью, выделенной с первым. - person Employed Russian; 10.10.2015
comment
Хорошо, я не видел, что есть ДВА звонка. Но баг тот же думаю я видел: так как дескриптор находится в стеке, то если память перемещается, указатель обновляется и эта позиция в стеке перезаписывается и возможно что-то испорчено. Я прав? - person Mabus; 10.10.2015
comment
@Mabus Нет, дескриптор в стеке не проблема. Тот факт, что вы до сих пор не нашли ошибку, должен служить хорошей иллюстрацией того, почему r_alloc сложно правильно использовать ;-) - person Employed Russian; 10.10.2015
comment
Это это проблема, потому что r_alloc хранит указатель на переменную для ее изменения при перемещении памяти. Может быть, ошибка, о которой вы говорите, заключается в том, что когда вы возвращаете значение, это фиксированный указатель, и он не изменится при перемещении памяти? - person Mabus; 10.10.2015
comment
@Mabus Вы правы, есть и эта проблема. Так что на самом деле здесь две отдельные ошибки. Вы нашли то, о чем я не подумал, но еще не то, что хотел проиллюстрировать. На самом деле, ваше последнее утверждение указывает на эту вторую ошибку. - person Employed Russian; 10.10.2015