2009-12-16 2 views
2

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

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

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

+0

Кстати, реализация malloc, которую я использую, имеет malloc_stats и mallinfo, но не malloc_set_state или malloc_get_state, которые могли бы (?) Предложить решение. – PypeBros

+0

выглядит как мой devkit использует mallocator «newlib». Я собираюсь изучить это, чтобы найти лучший способ исследовать проблему. – PypeBros

ответ

1

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

+0

... что, в свою очередь, подчеркивает тот факт, что загрузка приложения из ОЗУ из хранилища никогда не должна использоваться malloc() ... – PypeBros

3

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

2

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

1

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

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

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

0

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

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

Объекты могут все еще быть в этой обновленного очистки памяти с использованием Inplace нового оператора (т.е. новый, где вы указываете адрес памяти)

2

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

int* not_used = new i[1024]; 

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

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

+0

Хорошая идея. Это потребует некоторой настройки, потому что я игнорирую, где и сколько требуется памяти, но если мне удастся это выяснить, это может сделать трюк. Я не слишком уверен, что * нехватка памяти - это корень проблемы. Я боюсь, что переполнение буфера может также вызвать повреждение внутреннего состояния malloc. – PypeBros

1

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

 
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 очень ограничено, но для многих встроенных систем это было бы вполне адекватно.

+0

Да, к сожалению, я не могу упростить выделение памяти для этой точки. – PypeBros

+1

@sylvainulg: Этот подход управления памятью подходит для некоторых заданий, но не для всех. Небольшое отклонение состоит в том, чтобы иметь блок памяти, который выделяется как сверху, так и снизу (в этом случае независимо друг от друга можно делать релизы LIFO сверху и снизу). Третий вариант (используемый в 1980-х годах микрокомпьютер BASIC-переводчиков), если легко найти все указатели на память (с помощью двунаправленных указателей может помочь в этом), заключается в использовании уплотнения мусора вместо бесплатного списка. Этот подход имеет ограничения, но позволяет избежать фрагментации. – supercat

Смежные вопросы