Что из памяти обрабатывает стратегии в программировании C?

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

Затем, когда в любой программе точки malloc() возвраты NULL, Вы освобождаете 5 мегабайтов и вызов malloc() снова, который будет следовать и позволять программе продолжить работать.

Что Вы думаете об этой стратегии?

И что другие стратегии Вы знаете?

Спасибо, Boda Cydo.

7
задан bodacydo 13 August 2010 в 14:12
поделиться

9 ответов

Обработка сбоев malloc путем корректного выхода.В современных операционных системах, файлах подкачки и т. Д. Вы никогда не должны упреждающе готовиться к сбоям памяти, просто аккуратно завершите работу. Маловероятно, что вы когда-нибудь столкнетесь с ошибками нехватки памяти, если у вас нет алгоритмической проблемы.

Кроме того, безумие выделять 5 МБ без причины при запуске.

13
ответ дан 6 December 2019 в 06:48
поделиться

«попробуйте позже». То, что вы сейчас OOM, не означает, что вы вернетесь позже, когда система будет менее загружена.

void *smalloc(size_t size) {
   for(int i = 0; i < 100; i++) {
      void *p = malloc(size);
      if(p) 
        return p;
      sleep(1);
    }
   return NULL;
}

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

2
ответ дан 6 December 2019 в 06:48
поделиться

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

Такой сценарий может не относиться к вашему делу. Однако знание причин сбоя malloc () может быть полезно. Следующий метод, который мы используем в нашем коде, поскольку malloc () обычно недоступен, может (или не может) быть применимым к вашему сценарию.

Мы склонны полагаться на пулы памяти. Память для каждого пула выделяется во время переходной фазы запуска. Когда у нас есть пулы, мы получаем запись из пула, когда она нам нужна, и возвращаем ее обратно в пул, когда закончим. Каждый пул настраивается и обычно зарезервирован для определенного типа объекта. Мы можем отслеживать использование каждого из них с течением времени. Если у нас закончатся записи в пуле, мы сможем выяснить, почему. Если мы этого не сделаем, у нас есть возможность уменьшить наш пул и сэкономить некоторые ресурсы.

Надеюсь, это поможет.

5
ответ дан 6 December 2019 в 06:48
поделиться

Большинство современных операционных систем в конфигурации по умолчанию допускают чрезмерное использование памяти, поэтому ваша программа не получит NULL от malloc () вообще или, по крайней мере, до тех пор, пока она каким-то образом (по ошибке, я думаю) не исчерпает все доступное адресное пространство (не память). А затем он записывает совершенно допустимую ячейку памяти, получает ошибку страницы, в резервном хранилище нет страницы памяти и BANG (SIGBUS) - вы мертвы, и нет хорошего выхода.

Так что забудьте об этом, вы не сможете с этим справиться.

1
ответ дан 6 December 2019 в 06:48
поделиться

Да, на практике это не работает. Во-первых, по техническим причинам типичная реализация кучи с низким уровнем фрагментации не делает большие свободные блоки доступными для небольших распределений.

Но настоящая проблема в том, что вы не знаете , почему у вас закончилось пространство виртуальной памяти. И если вы не знаете, почему, то вы ничего не можете сделать, чтобы предотвратить очень быстрое потребление этой дополнительной памяти и по-прежнему сбой вашей программы с помощью OOM. Что очень вероятно, вы уже израсходовали около двух гигабайт, эти дополнительные 5 МБ - это капля воды на плиту.

Любая схема, переводящая приложение в «аварийный режим», очень непрактична.Вам придется прервать выполнение кода, чтобы, скажем, остановить загрузку огромного файла данных. Это требует исключения. Теперь вы вернулись к тому, что у вас уже было, std :: badalloc.

1
ответ дан 6 December 2019 в 06:48
поделиться

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

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

1
ответ дан 6 December 2019 в 06:48
поделиться

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

Некоторые приложения, например, проигрыватель музыки или фильмов, вполне оправданно выходят из системы или аварийно завершают работу при сбоях в распределении - они управляют небольшим количеством изменяемых данных. С другой стороны, я считаю, что любое приложение, которое используется для изменения потенциально ценных данных, должно иметь способ (1) гарантировать, что данные, уже находящиеся на диске, останутся в последовательном, не поврежденном состоянии, и (2) записывать журнал восстановления, чтобы при последующих обращениях пользователь мог восстановить любые данные, потерянные при принудительном закрытии приложения.

Как мы видели в первом абзаце, из-за условий гонки ваш подход "malloc 5mb и освободить его" не работает. В идеале код для синхронизации данных и записи информации о восстановлении должен быть полностью свободен от выделений; если ваша программа хорошо спроектирована, она, вероятно, естественным образом свободна от выделений. Один из возможных подходов, если вы знаете, что вам понадобятся выделения на этом этапе, - реализовать свой собственный аллокатор, работающий в небольшом статическом буфере/пуле, и использовать его во время отключения сбоя выделения.

0
ответ дан 6 December 2019 в 06:48
поделиться

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

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

2
ответ дан 6 December 2019 в 06:48
поделиться

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

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

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

Имейте в виду, что когда вы получаете NULL из malloc , это означает, что и в физической, и в виртуальной памяти больше нет свободного места, что означает, что ваша программа все время меняет местами, что делает ее медленно и компьютер не отвечает.

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

1
ответ дан 6 December 2019 в 06:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: