好吧,您可以在启动时甚至在.bss
编译时分配大约16个MiB(只能确保100%保证),并使用“安全分配器”,其签名类似inline __attribute__((force_inline)) void* alloc(size_t size)
(__attribute__((force_inline))
是一个GCC / mingw-w64
属性,用于强制内联关键代码节即使禁用优化(即使应该为游戏启用优化)也不会malloc
尝试,void* result = malloc(size)
并且如果失败,则删除缓存,释放备用内存(或告诉其他代码使用该.bss
事物,但这超出了此答案的范围)刷新未保存的数据(将世界保存到磁盘,如果您使用类似Minecraft的大块概念,请调用saveAllModifiedChunks()
)。然后,如果malloc(16777216)
(再次分配这16个MiB)失败(再次,将替换为.bss
),则终止游戏并显示MessageBox(NULL, "*game name* couldn't continue because of lack of free memory, but your world was safely saved. Try closing background applications and restarting the game", "*Game name*: out of memory", MB_ICONERROR)
或特定于平台的替代方案。放在一起:
__attribute__((force_inline)) void* alloc(size_t size) {
void* result = malloc(size); // Attempt to allocate normally
if (!result) { // If the allocation failed...
if (!reserveMemory) std::_Exit(); // If alloc() was called from forceFullSave() or reportOutOfMemory() and we again can't allocate, just quit, something is stealing all our memory. If we used the .bss approach, this wouldn't've been necessary.
free(reserveMemory); // Global variable, pointer to the reserve 16 MiB allocated on startup
forceFullSave(); // Saves the game
reportOutOfMemory(); // Platform specific error message box code
std::_Exit(); // Close silently
} else return result;
}
您可以使用类似的解决方案std::set_new_handler(myHandler)
,其中myHandler
在void myHandler(void)
这时候,所谓的new
失败:
void newerrhandler() {
if (!reserveMemory) std::_Exit(); // If new was called from forceFullSave() or reportOutOfMemory() and we again can't allocate, just quit, something is stealing all our memory. If we used the .bss approach, this wouldn't've been necessary.
free(reserveMemory); // Global variable, pointer to the reserve 16 MiB allocated on startup
forceFullSave(); // Saves the game
reportOutOfMemory(); // Platform specific error message box code
std::_Exit(); // Close silently
}
// In main ()...
std::set_new_handler(newerrhandler);