Skip to content

Commit 440972d

Browse files
committed
Fix memory leak in synthetic SPVVariable allocation
Replace malloc + placement new with std::unique_ptr for synthetic SPVVariable objects created for device-only variables (e.g., templated __constant__ variables). The static vector now stores unique_ptr which ensures proper destruction of std::string members and memory deallocation when the program exits.
1 parent c883571 commit 440972d

1 file changed

Lines changed: 20 additions & 21 deletions

File tree

src/CHIPBackend.cc

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,20 +1186,21 @@ chipstar::Module *chipstar::Device::getOrCreateModule(HostPtr Ptr) {
11861186
// Discover device-only variables (e.g., template instantiations) that weren't
11871187
// registered via __hipRegisterVar. These have shadow kernels but no host symbol.
11881188
static int DummyHostPtr = 0;
1189-
static std::vector<SPVVariable*> SyntheticVars;
1190-
1189+
// Use unique_ptr for automatic cleanup when the program exits
1190+
static std::vector<std::unique_ptr<SPVVariable>> SyntheticVars;
1191+
11911192
for (auto *Kernel : Mod->getKernels()) {
1192-
const std::string& KernelName = Kernel->getName();
1193+
const std::string &KernelName = Kernel->getName();
11931194
size_t PrefixLen = strlen(ChipVarInfoPrefix);
1194-
1195+
11951196
// Check if this is a variable info shadow kernel
11961197
if (KernelName.length() <= PrefixLen ||
11971198
KernelName.substr(0, PrefixLen) != ChipVarInfoPrefix)
11981199
continue;
1199-
1200+
12001201
// Extract variable name
12011202
std::string VarName = KernelName.substr(PrefixLen);
1202-
1203+
12031204
// Check if we already processed this variable
12041205
bool AlreadyRegistered = false;
12051206
for (const auto &Info : SrcMod->Variables) {
@@ -1209,27 +1210,25 @@ chipstar::Module *chipstar::Device::getOrCreateModule(HostPtr Ptr) {
12091210
break;
12101211
}
12111212
}
1212-
1213+
12131214
if (AlreadyRegistered)
12141215
continue;
1215-
1216+
12161217
// This is a device-only variable - create a DeviceVar for it without a host pointer
12171218
logTrace("Found device-only variable: {} (no host symbol)", VarName);
1218-
1219+
12191220
// Create a synthetic SPVVariable for this device-only variable
1220-
// Manually allocate and initialize all fields
1221-
SPVVariable *SyntheticVar = (SPVVariable *)malloc(sizeof(SPVVariable));
1222-
SyntheticVar->Parent = const_cast<SPVModule*>(SrcMod);
1223-
new (&SyntheticVar->Ptr) HostPtr(&DummyHostPtr); // placement new for HostPtr
1224-
new (&SyntheticVar->Name) std::string(VarName); // placement new for std::string
1225-
SyntheticVar->Size = 0;
1226-
1227-
auto *Var = new chipstar::DeviceVar(SyntheticVar);
1221+
// Use aggregate initialization since SPVVariable has no default constructor
1222+
auto *RawVar = new SPVVariable{
1223+
{const_cast<SPVModule *>(SrcMod), HostPtr(&DummyHostPtr), VarName}, 0};
1224+
std::unique_ptr<SPVVariable> SyntheticVar(RawVar);
1225+
1226+
auto *Var = new chipstar::DeviceVar(SyntheticVar.get());
12281227
Mod->addDeviceVariable(Var);
1229-
1230-
// Store the synthetic variable so it persists
1231-
SyntheticVars.push_back(SyntheticVar);
1232-
1228+
1229+
// Store the synthetic variable so it persists (unique_ptr handles cleanup)
1230+
SyntheticVars.push_back(std::move(SyntheticVar));
1231+
12331232
// Note: We don't add to DeviceVarLookup_ since there's no host pointer to look up
12341233
}
12351234

0 commit comments

Comments
 (0)