C ++ 게임은 메모리 할당 실패를 어떻게 처리합니까?


23

C ++로 작성된 몇 가지 게임을 알고 있지만 예외는 사용하지 않습니다. C ++에서 메모리 할당 실패 처리는 일반적으로 std::bad_alloc예외를 중심으로하기 때문에 이러한 게임은 이러한 실패를 어떻게 처리합니까?

그들은 단순히 충돌합니까, 아니면 메모리 부족 오류를 처리하고 복구하는 다른 방법이 있습니까?


1
할당이 성공했다고 주장하는 특정 환경 / OS가 있지만 메모리를 사용하려고하면 (또는 다른) 프로그램이 충돌합니다.
PlasmaHH

6
게임 도중 할당이 실패하면 Quake 3는 오류 메시지와 함께 메뉴로 ​​돌아갑니다. 나는 이것이 Quake 3의 풀 할당 자에 의해 가능하다고 생각합니다 .Quick 3의 풀 할당자는 풀 전체를 버리고 풀이 부족하면 메뉴로 안전하게 돌아갈 수 있습니다.
Dietrich Epp

16
일반적으로 충돌합니다.
user253751

1
예외가 std::terminate실제로 비활성화되어있는 경우 프로그램은 대신을 호출해야 합니다. 그러나 동일한 제한 하에서 할당은 예외를 발생시키는 대신 널 포인터를 리턴 할 수 있으며, 그 결과를 별도로 확인하고 처리 할 수 ​​있습니다.
underscore_d

2
C ++에서, 당신은 말할 수있다 ClassName variableName = new(nothrow) ClassName();( 분명히 클래스 이름, 변수 이름 등 대체 할당이 실패한다면, 당신이 말하는하여 검색 할 수 있습니다) if(!variableName)오류가 시도 - 캐치 예외 블록없이 처리 할 수 있도록합니다. 메모리가 같은 함수를 사용하여 할당되어있는 경우 마찬가지로 malloc(), calloc()할당 한 후 등의 실패를 동일한 사용하여 검출 될 수 if(!variableName)시도 캐치 없이도 방법. 게임이 이러한 오류를 처리하는 방법에 관해서는, 그 시점에서 게임 개발자는 충돌 여부를 결정해야합니다.
스펜서 D

답변:


63

모든 일반 프로그램과 동일 : 그렇지 않습니다. *

대부분의 응용 프로그램에서 메모리가 소진 된 후에도 계속 작동 할 것이라는 고객의 기대는 없습니다. 모든 게임은 이러한 "대부분의 응용 프로그램"에 속합니다. 고객이 기대하지 않는 최첨단 사례에서 작업하는 데 시간과 돈을 소비하는 것은 의미가 없습니다.

질문은 다음과 유사합니다.

  • 하드 디스크가 꽉 찬 경우 어떻게 게임을 설치합니까?
  • 최소 사양 미만의 PC에서 여전히 높은 fps로 게임을 실행하는 방법은 무엇입니까?

대답은 동일합니다. 사용자의 문제입니다. 게임은 상관하지 않습니다.


* 실제로, 그들은 일반적으로 예외에 대한 높은 수준의 캐치를 수행하고, 충돌 / 종료 전에 이벤트를 기록하기 위해 게임 시작시 사전 할당 된 메모리를 사용합니다. 그런 다음이 로그를 통해 고객 지원 부서에서 문제에 대한 시간을 줄일 수 있습니다.


2
: 메모리 할당 실패시 등에 기록 용 메모리를 사전 할당에 stackoverflow.com/questions/7749066/...
bwDraco

23

일반적으로 이런 종류의 시나리오는 발생하지 않습니다.

첫째, 최신 운영 체제의 가상 메모리는 어쨌든 정상적인 운영에서는 발생하지 않을 가능성이 높다는 것을 의미합니다. 런 어웨이 할당 버그가없는 한, 게임은 OS 가상 주소 공간에서 메모리를 할당하고 OS는 페이징 및 페이징 후 감시합니다.

그것은 모두 좋고 훌륭하지만 실제로 콘솔이나 구형 OS에는 적용되지 않으므로 두 번째로 게임은 표준 라이브러리 할당자를 사용하여 작은 동적 할당을 많이하지 않습니다. 대신 그들이 할 일은 시작할 때 한 번만 큰 메모리 풀을 할당하고 필요한 런타임 할당을 위해 해당 풀에서 내려주는 것입니다 (예 : C ++ 배치를 사용하거나 자체 메모리 관리 시스템을 작성하여) 그것의 상단).

또한 각각의 작은 개별 할당을 추적하고 설명하지 않고 메모리 누수를 방지하기 위해 전체 풀을 버리고 메모리를 되 찾을 수 있습니다.

셋째, 게임은 항상 최소 사양을 설정하고 그 내에서 메모리 사용을 계획합니다. 따라서 게임이 1GB의 RAM을 요구하도록 지정된 경우, 메모리 사용량이 1GB를 초과하지 않는 한 RAM 부족에 대해 걱정할 필요가 없습니다.


3
"그 대신에 시작할 때 큰 메모리 풀을 한 번만 할당하고 필요한 런타임 할당에 대해 해당 풀에서 그립니다."-풀이 가득 찬 경우 어떻게 생각하십니까?
user253751

@immibis-내 세 번째 요점을 참조하십시오.
Maximus Minimus

2
@immibis 당신은 ... 수영장이 비어 있으면 무엇을합니까? 시스템 메모리와 달리 풀의 크기와 사용량은 완전히 응용 프로그램이 제어합니다. 따라서 응용 프로그램에 버그가 없으면 풀 비울 수 없습니다 .
David Schwartz

@DavidSchwartz 또는 커널이 메모리 오버 커밋을 사용하지 않는 한. 리눅스는 이것을한다. zswap 또는 zram을 통해 페이지 파일 압축이 활성화 된 경우 풀을 0으로 설정해도 도움이되지 않습니다.
Damian Yerrick

1
이것은 실제 질문에 대답하는 것 같지 않지만 대신 "이 함선은 침몰 할 수 없으므로 비상 절차가 필요한 이유는 무엇입니까?"
Lilienthal

2

글쎄, 주로 예외가 존재하기 전에 우리가했던 것과 같은 방식-오래된 "반환 값 접근 방식 확인". 할당자가 예외를 사용하지 않으면 일반적으로 null할당이 실패하면 반환 됩니다. 잘 작성된 게임은이를 확인하고 안전한 방식으로 상황을 처리합니다. 때로는 게임 종료 (예 std::terminate:) 또는 마지막으로 알려진 안전 상태로 복귀 (예 : 풀에서 할당 할 때 안전하지 않은 상태에서도 전체 풀을 안전하게 처리 할 수 ​​있음)를 의미합니다.

많은 게임은 이런 경우에도 예외를 사용합니다. 누군가가 "게임 코드에서 예외 사용을 피하십시오"라고 말할 때, 일반적으로 의미하는 것은 "일반적인 흐름 제어가 아닌 예외적 인 경우에만 예외를 사용하는 것"입니다. 메모리 부족 예외를 잡기위한 설정은 저렴합니다. 비용은 대부분 던져지고 예외를 처리 할 때 발생하는 복잡한 문제입니다. 이 중 어느 것도 전형적인 메모리 부족 사례에서 매우 중요하지 않습니다. 거의 항상 종료하고 싶습니다.

대부분의 게임은 중단 될 것입니다. 이것은 소리만큼 나쁘지는 않습니다. 일반적으로 메모리 사용량이 대상으로 설정되어 있고 게임이 해당 제한에 도달하지 않는지 확인하십시오 (예 : RTS 게임에서 단위 수 제한을 사용하거나 FPS 섹션에있는 적의 양). 그렇지 않은 경우에도 일반적으로 최신 시스템의 메모리가 부족하지 않습니다. 예를 들어 가상 주소 공간 (32 비트 응용 프로그램) 또는 스택이 부족합니다. OS는 이미 원하는만큼의 메모리를 가지고 있다고 가정합니다. 이는 가상 메모리가 제공하는 추상화 중 하나입니다. 요점은 256MiB의 실제 RAM이 있다고해서 애플리케이션이 4GiB의 메모리를 사용할 수 없다는 것을 의미하지는 않습니다. 일부 게임은 모든 데이터가 너무 마음에 들지 않을 수도 있습니다.


1

예외 포착하고 언제 그리고 예외가 발생했는지를 결정하는 것은 서로 다른 두 가지입니다.

프로그램에 필요하지 않은 메모리를 확보하려면 복잡한 논리가 필요합니다. 더 나쁜 것은, 다른 실행중인 프로그램이나 라이브러리가 메모리를 누출하는 경우 제어 할 수없는 것입니다

정상적으로 종료하기 위해 할 수있는 가장 좋은 방법은 대부분의 프로그램이 선택한 것입니다. 프로그램이 응답하지 않기 때문에 메모리를 사용할 수있을 때까지 기다릴 수도 없습니다.


OP가 말한 것처럼 문제의 게임이 문자 그대로 "예외를 사용하지 않는 경우"는 게임을 잡거나 제기하거나 처리 할 수 ​​없습니다. 예외가 비활성화되고 누군가가 예외를 throw하면 프로그램은 대신을 호출해야 std::terminate합니다. 그러나 이러한 조건에서 할당은 예외를 발생시키는 대신 null 포인터를 반환 할 수 있으며 별도로 처리 할 수 ​​있습니다.
underscore_d
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.