Skip to content

Commit 434f975

Browse files
ChinChangYangclaude
andcommitted
RAII the gzFile handle in KataGoParser
Own the gzFile with a custom-deleter unique_ptr so it closes on every exit path (normal return, exception, bad_alloc); removes the manual try/catch+gzclose in parse() and the ordering caveat on buffer allocation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent ce0b00a commit 434f975

2 files changed

Lines changed: 17 additions & 19 deletions

File tree

cpp/external/katagocoreml/src/parser/KataGoParser.cpp

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ bool KataGoParser::isVersionSupported(int version) {
3333
// ============================================================================
3434

3535
bool KataGoParser::refill() {
36-
if(m_gz == nullptr) return false;
37-
int n = gzread(m_gz, m_refill.data(), (unsigned)m_refill.size());
36+
if(!m_gz) return false;
37+
int n = gzread(m_gz.get(), m_refill.data(), (unsigned)m_refill.size());
3838
if(n < 0) {
3939
int errnum;
40-
const char* errmsg = gzerror(m_gz, &errnum);
40+
const char* errmsg = gzerror(m_gz.get(), &errnum);
4141
throw std::runtime_error("Error reading gzip stream: " + std::string(errmsg));
4242
}
4343
m_refillPos = 0;
@@ -72,27 +72,17 @@ void KataGoParser::readExact(uint8_t* dst, size_t n, const std::string& name) {
7272
// ============================================================================
7373

7474
KataGoModelDesc KataGoParser::parse() {
75-
// Allocate the refill buffer before opening the file so a bad_alloc here
76-
// cannot leak an open gzFile handle.
75+
// Allocate the refill buffer first; if this throws, no handle has been opened.
7776
m_refill.resize(1024 * 1024);
78-
m_gz = gzopen(m_model_path.c_str(), "rb");
79-
if(m_gz == nullptr)
77+
m_gz.reset(gzopen(m_model_path.c_str(), "rb"));
78+
if(!m_gz)
8079
throw std::runtime_error("Cannot open file: " + m_model_path);
8180
m_refillPos = 0;
8281
m_refillLen = 0;
8382
m_formatDetected = false; // decided at first readFloats
8483
m_binary_floats = true;
85-
KataGoModelDesc model;
86-
try {
87-
model = parseModel();
88-
} catch(...) {
89-
gzclose(m_gz);
90-
m_gz = nullptr;
91-
throw;
92-
}
93-
gzclose(m_gz);
94-
m_gz = nullptr;
95-
return model;
84+
// ~GzHandle closes the file on normal return OR exception — no try/catch needed.
85+
return parseModel();
9686
}
9787

9888
// ============================================================================

cpp/external/katagocoreml/src/parser/KataGoParser.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
#include "../types/KataGoTypes.hpp"
77
#include <array>
8+
#include <memory>
89
#include <string>
10+
#include <type_traits>
911
#include <vector>
1012
#include <zlib.h>
1113

@@ -32,7 +34,13 @@ class KataGoParser {
3234

3335
private:
3436
std::string m_model_path;
35-
gzFile m_gz = nullptr;
37+
// Custom-deleter unique_ptr owns the gzFile so it closes on every exit path
38+
// (normal return, exception, or bad_alloc) without manual try/catch.
39+
struct GzCloser {
40+
void operator()(gzFile f) const noexcept { if(f) gzclose(f); }
41+
};
42+
using GzHandle = std::unique_ptr<std::remove_pointer_t<gzFile>, GzCloser>;
43+
GzHandle m_gz;
3644
std::vector<uint8_t> m_refill; // bounded refill buffer (~1 MB)
3745
size_t m_refillPos = 0; // read cursor within m_refill
3846
size_t m_refillLen = 0; // valid bytes in m_refill

0 commit comments

Comments
 (0)