Мне известно о нескольких играх, написанных на C ++, но не использующих исключения. Так как обработка ошибки выделения памяти в C ++ обычно строится вокруг std::bad_alloc
исключения, как эти игры справляются с такой ошибкой?
Они просто аварийно завершают работу или есть другой способ обработки и восстановления после ошибки нехватки памяти?
c++
resource-management
memory
user200783
источник
источник
std::terminate
, и это все. Но тогда, с тем же ограничением, распределение может возвращать нулевой указатель вместо исключения, и этот результат может быть проверен и обработан отдельно.ClassName variableName = new(nothrow) ClassName();
( очевидно, заменяя имя класса, имя переменной и т. Д. ). Затем, если распределение завершится неудачно, вы можете обнаружить это, сказав,if(!variableName)
что ошибка может быть обработана без блока исключения try-catch. Точно так же, если память выделяется с использованием функции , какmalloc()
,calloc()
и т.д., то отказы выделить могут быть обнаружены с использованием того жеif(!variableName)
метода без необходимости Try-улов. Что касается того, как игры справляются с этими ошибками, ну, на этом этапе, разработчики игры должны решить, сбоит она или нет.Ответы:
То же, что и все средние программы: нет. *
Для большинства приложений не ожидается, что они продолжат работать после исчерпания памяти. Все игры подпадают под эти "большинство приложений". Тратить время и деньги на работу в крайнем случае, который клиент не ожидает, не имеет смысла.
Вопрос похож на следующее:
Ответ тот же: это проблемы пользователей. Игра не волнует.
* На самом деле, они обычно делают высокий уровень перехвата исключения и используют память, которая была предварительно выделена в начале игры, чтобы попытаться записать событие перед сбоем / завершением. Журнал позволяет службе поддержки тратить меньше времени на решение проблемы.
источник
Как правило, такого рода сценарий никогда не происходит.
Во-первых, виртуальная память в современных операционных системах означает, что в любом случае это вряд ли произойдет при нормальной работе; если только у вас не будет ошибки размещения, игра будет выделять память из виртуального адресного пространства ОС, а ОС будет следить за входом и выходом.
Это все хорошо, но на самом деле это не относится к консолям или старым ОС, поэтому, во-вторых, игры в любом случае даже не выполняют много небольших динамических распределений, используя стандартные распределители библиотек. Вместо этого они будут выделять большой пул памяти только один раз при запуске и использовать этот пул для любых требуемых выделений во время выполнения (например, с помощью нового размещения C ++ или написания собственной системы управления памятью в вершина этого).
Это также защищает от утечек памяти, потому что вместо того, чтобы отслеживать и учитывать каждое маленькое отдельное распределение, игра может просто выбросить весь пул для восстановления памяти.
И в-третьих, игры всегда будут устанавливать минимальные спецификации и планировать использование памяти. Таким образом, если для игры требуется 1 ГБ ОЗУ, это означает, что до тех пор, пока ее использование памяти никогда не превышает 1 ГБ, ей не нужно беспокоиться об исчерпании ОЗУ.
источник
Ну, в основном, так же, как мы делали это до появления исключений - старый метод «проверьте возвращаемое значение». Если распределитель не использует исключения, он обычно возвращается
null
при сбое выделения. Хорошо написанная игра проверит это и разрешит ситуацию любым безопасным способом. Иногда это означает прекращение игры (например,std::terminate
) или, по крайней мере, возврат к последнему известному безопасному состоянию (например, когда вы выделяете из пула, вы можете безопасно утилизировать весь пул, даже когда он находится в небезопасном состоянии).Многие игры используют исключения для подобных случаев даже тогда. Когда кто-то говорит «избегайте использования исключений в игровом коде», они обычно имеют в виду «используйте исключения только для действительно исключительных случаев, а не для мирского управления потоком». Установка для отлова исключения из нехватки памяти обходится дешево - стоимость в основном на ходу, а также сложности, возникающие при обработке исключения. Ни один из них не очень важен в типичном случае нехватки памяти - вы почти всегда хотите завершить в любом случае.
Имейте в виду, большинство игр просто рухнет. Это не так безумно, как кажется - у вас обычно есть некоторое использование памяти в качестве цели, и убедитесь, что ваша игра не достигает этого предела (например, используя ограничение количества юнитов в игре RTS или ограничивая количество врагов в разделе FPS). Даже если вы этого не сделаете, у вас обычно не хватает памяти в какой-либо достаточно современной системе - например, у вас заканчивается виртуальное адресное пространство (в 32-разрядном приложении) или стек. ОС уже делает вид, что у вас столько памяти, сколько вы просите - это одна из абстракций, которую предоставляет виртуальная память. Дело в том, что наличие 256 МБ физической памяти не означает, что ваше приложение не может использовать 4 ГБ памяти. Некоторые игры могут даже не возражать, что все их данные не
источник
Поймать исключение и решить, что, когда и когда возникает исключение, это две разные вещи.
Вы должны иметь сложную логику, чтобы освободить память, которая не нужна вашей программе. Хуже того, если какая-либо другая запущенная программа или библиотека вытекла из памяти, вы не можете ее контролировать
Только хорошо, что вы можете сделать это, чтобы корректно завершить работу, и именно это выберет большинство программ. Вы даже не можете дождаться, пока память станет доступной, потому что это сделает вашу программу не отвечающей.
источник
std::terminate
, и это все. Но в таких условиях распределение может возвращать нулевой указатель вместо исключения, и это может быть обработано отдельно.