вернуть malloc () в исходное состояние - PullRequest
2 голосов
/ 16 декабря 2009

Знаете ли вы, есть ли способ вернуть malloc в исходное состояние, как если бы программа только начиналась?

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

Я подозреваю, что код, который я использую для "мягкой перезагрузки", включает сам malloc () в какой-то момент, который я не могу контролировать, поэтому я хотел бы "забыть все о запущенном приложении и начать все сначала".

Ответы [ 7 ]

3 голосов
/ 16 декабря 2009

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

2 голосов
/ 16 декабря 2009

Извлеките немного памяти в глобальном местоположении, например,

int* not_used = new i[1024];

Затем, когда вы получите std::bad_alloc, удалите not_used и перейдите к консоли ошибок. Идея состоит в том, чтобы дать вашему обработчику сбоя достаточно места, чтобы сделать то, что вам нужно. Вам нужно настроить, сколько памяти зарезервировано, чтобы ваша консоль также не получала ошибок нехватки памяти.

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

2 голосов
/ 16 декабря 2009

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

1 голос
/ 20 декабря 2010

Вам когда-нибудь нужно освобождать память в порядке, отличном от последнего в порядке очереди? Если нет, я бы предложил, чтобы вы определили массив для использования всей доступной памяти (вам, вероятно, придется настроить файлы компоновки), а затем инициализировали указатель на начало этого массива. Затем напишите свою собственную функцию malloc ():

char *allocation_ptr = big_array;

void *malloc(size_t n)
{
  void *temp = (void*)allocation_ptr;
  if (allocation_ptr > END_OF_ALLOCATION_AREA - n)
    return 0;
  allocation_ptr += n;
  return temp;
}

void free_all_after(void *ptr)
{
  if (ptr)
    allocation_ptr = (char*)ptr;
}

В этой реализации free_all_after () освободит указанный указатель и все, что выделено после него . Обратите внимание, что в отличие от других реализаций malloc (), эта накладная часть имеет ноль . Распределение LIFO очень ограничено, но для многих встроенных систем оно будет вполне адекватным.

1 голос
/ 14 января 2010

Единственный способ начать все сначала - перезагрузить приложение из хранилища. DS загружает все в RAM, что означает, что раздел данных изменяется на месте.

1 голос
/ 16 декабря 2009

Полагаю, если больше ничего не работает, вы могли бы записать в ноль весь блок памяти, который API предоставляет в Nintendo? Но в остальном просто следите за вашими ассигнованиями.

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

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

0 голосов
/ 16 декабря 2009

std :: bad_alloc возникает при сбое нового и не может выделить запрошенную память. Это обычно происходит, когда куча исчерпала память и поэтому не может выполнить запрос. По этой причине вы не сможете надежно выделить новую память в процессе очистки.

Это означает, что вы не можете выделять новую память для очистки. Ваша единственная надежда на успешную очистку состоит в том, чтобы убедиться, что память для кода очистки предварительно выделена задолго до того, как она вам действительно понадобится.

Объекты по-прежнему могут быть добавлены в эту память очистки с помощью оператора new на месте (т. Е. New, где вы указали адрес памяти)

...