Savestates: Allocate the load buffer with malloc rather than new (std::nothrow)

new (std::nothrow) doesn't work with DbgNew.h's new macro in Windows debug
builds. The buffer is only ever freed in two places, so switch them to free().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-11-05 14:08:56 +01:00
1 parent ebafb89215
commit 5fcb29d37e
3 files changed
+15 -14

No files matched your search

+11 -12
View File
@@ -18,7 +18,6 @@
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <new>
#include <snappy-c.h>
#include <zstd.h>
@@ -513,13 +512,13 @@ CChunkFileReader::Error CChunkFileReader::LoadFile(const Path &filename, std::st
}
if (SerializeCompressType(header.Compress) == SerializeCompressType::ZSTD) {
u8 *uncomp_buffer = new (std::nothrow) u8[header.UncompressedSize];
u8 *uncomp_buffer = (u8 *)malloc(header.UncompressedSize);
if (!uncomp_buffer) {
return ERROR_BAD_FILE;
}
if (!DecompressZstdFromFile(pFile, header.ExpectedSize, uncomp_buffer, header.UncompressedSize)) {
ERROR_LOG(Log::SaveState, "ChunkReader: Failed to decompress file");
delete [] uncomp_buffer;
free(uncomp_buffer);
return ERROR_BAD_FILE;
}
_buffer = uncomp_buffer;
@@ -530,18 +529,18 @@ CChunkFileReader::Error CChunkFileReader::LoadFile(const Path &filename, std::st
// Uncompressed, or snappy (older states).
sz = header.ExpectedSize;
u8 *buffer = new (std::nothrow) u8[sz];
u8 *buffer = (u8 *)malloc(sz);
if (!buffer || !pFile.ReadBytes(buffer, sz))
{
ERROR_LOG(Log::SaveState, "ChunkReader: Error reading file");
delete [] buffer;
free(buffer);
return ERROR_BAD_FILE;
}
if (header.Compress) {
u8 *uncomp_buffer = new (std::nothrow) u8[header.UncompressedSize];
u8 *uncomp_buffer = (u8 *)malloc(header.UncompressedSize);
if (!uncomp_buffer) {
delete [] buffer;
free(buffer);
return ERROR_BAD_FILE;
}
size_t uncomp_size = header.UncompressedSize;
@@ -554,19 +553,19 @@ CChunkFileReader::Error CChunkFileReader::LoadFile(const Path &filename, std::st
}
if (!success) {
ERROR_LOG(Log::SaveState, "ChunkReader: Failed to decompress file");
delete [] uncomp_buffer;
delete [] buffer;
free(uncomp_buffer);
free(buffer);
return ERROR_BAD_FILE;
}
if ((u32)uncomp_size != header.UncompressedSize) {
ERROR_LOG(Log::SaveState, "Size mismatch: file: %u calc: %u", header.UncompressedSize, (u32)uncomp_size);
delete [] uncomp_buffer;
delete [] buffer;
free(uncomp_buffer);
free(buffer);
return ERROR_BAD_FILE;
}
_buffer = uncomp_buffer;
sz = uncomp_size;
delete [] buffer;
free(buffer);
} else {
_buffer = buffer;
}
+2 -1
View File
@@ -303,7 +303,7 @@ public:
if (error == ERROR_NONE) {
failureReason->clear();
error = LoadPtr(ptr, sz, _class, failureReason);
delete [] ptr;
free(ptr);
INFO_LOG(Log::SaveState, "ChunkReader: Done loading '%s'", filename.c_str());
} else {
WARN_LOG(Log::SaveState, "ChunkReader: Error found during load of '%s'", filename.c_str());
@@ -359,6 +359,7 @@ public:
// The file half of Load() and Save(), for doing it away from the state itself. LoadFile hands back
// a new[]'d buffer; SaveFile takes ownership of a malloc'd one (as from MeasureAndSavePtr).
// The buffer is allocated with malloc (so the allocation can fail cleanly), free it with free().
static Error LoadFile(const Path &filename, std::string *gitVersion, u8 *&buffer, size_t &sz);
// Reads only the first size bytes of the state, decompressing no more than that. Not for snappy
// compressed (old) states.
+2 -1
View File
@@ -122,7 +122,8 @@ enum class OperationType {
struct PendingRead {
std::atomic<bool> done{ false };
CChunkFileReader::Error error = CChunkFileReader::ERROR_NONE;
std::unique_ptr<u8[]> buffer;
// From LoadFile, so malloc'd.
std::unique_ptr<u8, decltype(&free)> buffer{ nullptr, &free };
size_t size = 0;
std::string gitVersion;
// "PPSSPP <version>" from the header, for the failure message.