Skip to content

Commit 32cef71

Browse files
committed
fix: INFRA memory leak
1 parent 2a47a4c commit 32cef71

File tree

6 files changed

+128
-0
lines changed

6 files changed

+128
-0
lines changed

src/Modules.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
#include "Modules/Surface.hpp"
1212
#include "Modules/Tier1.hpp"
1313
#include "Modules/VGui.hpp"
14+
#include "Modules/VPhysics.hpp"

src/Modules/VPhysics.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include "VPhysics.hpp"
2+
3+
#include "Event.hpp"
4+
#include "Interface.hpp"
5+
#include "Offsets.hpp"
6+
#include "SAR.hpp"
7+
8+
9+
// Kinda a silly way to keep track of this, but it works
10+
// and I'm lazy
11+
static std::vector<int *> vphysEnvironments;
12+
static std::vector<int *> vphysEnvironmentsLast;
13+
14+
// INFRA memory leak
15+
// The game has a "fast load" feature that skips a bunch of stuff, including
16+
// destroying the old physics environment. This leaks ~4MB (one env) per load.
17+
// Slow loads destroy the two environments that are in use, and create a new
18+
// two. We detect this and destroy the old environments that are no longer in
19+
// use. There are other leaks, but this is the most significant.
20+
ON_EVENT(SESSION_START) {
21+
if (!sar.game->Is(SourceGame_INFRA)) return;
22+
vphysEnvironmentsLast = vphysEnvironments;
23+
vphysEnvironments = {};
24+
for (int i = 0; ; ++i) {
25+
int *env = vphysics->GetActivePhysicsEnvironmentByIndex(i);
26+
if (!env) break;
27+
vphysEnvironments.push_back(env);
28+
}
29+
30+
// console->Print("%d active physics environment(s)\n", (int)vphysEnvironments.size());
31+
// int i = 0;
32+
// for (const auto &env : vphysEnvironmentsLast) {
33+
// if (std::find(vphysEnvironments.begin(), vphysEnvironments.end(), env) == vphysEnvironments.end()) {
34+
// console->ColorMsg(Color(255,96,64), "- %d %p\n", i, env);
35+
// }
36+
// i++;
37+
// }
38+
// i = 0;
39+
// for (const auto &env : vphysEnvironments) {
40+
// if (std::find(vphysEnvironmentsLast.begin(), vphysEnvironmentsLast.end(), env) == vphysEnvironmentsLast.end()) {
41+
// console->ColorMsg(Color(96,255,64), "+ %d %p\n", i, env);
42+
// } else {
43+
// console->Print(" %d %p\n", i, env);
44+
// }
45+
// i++;
46+
// }
47+
48+
int newEnvs = 0;
49+
for (const auto &env : vphysEnvironments) {
50+
if (std::find(vphysEnvironmentsLast.begin(), vphysEnvironmentsLast.end(), env) == vphysEnvironmentsLast.end()) {
51+
newEnvs++;
52+
}
53+
}
54+
if (newEnvs == 2) {
55+
for (const auto &env : vphysEnvironments) {
56+
if (std::find(vphysEnvironmentsLast.begin(), vphysEnvironmentsLast.end(), env) != vphysEnvironmentsLast.end()) {
57+
vphysics->DestroyPhysicsEnvironment(env);
58+
}
59+
}
60+
}
61+
}
62+
63+
int *VPhysics::GetActivePhysicsEnvironmentByIndex(int index) {
64+
if (!this->GetActiveEnvironmentByIndex) return nullptr;
65+
return this->GetActiveEnvironmentByIndex(this->g_pVphysics->ThisPtr(), index);
66+
}
67+
68+
void VPhysics::DestroyPhysicsEnvironment(int *env) {
69+
if (!this->DestroyEnvironment) return;
70+
this->DestroyEnvironment(this->g_pVphysics->ThisPtr(), env);
71+
}
72+
73+
bool VPhysics::Init() {
74+
this->g_pVphysics = Interface::Create(this->Name(), "VPhysics031", false);
75+
76+
if (Offsets::GetActiveEnvironmentByIndex) {
77+
GetActiveEnvironmentByIndex = g_pVphysics->Original<_GetActiveEnvironmentByIndex>(Offsets::GetActiveEnvironmentByIndex);
78+
}
79+
if (Offsets::DestroyEnvironment) {
80+
DestroyEnvironment = g_pVphysics->Original<_DestroyEnvironment>(Offsets::DestroyEnvironment);
81+
}
82+
83+
return this->hasLoaded = this->g_pVphysics;
84+
}
85+
86+
void VPhysics::Shutdown() {
87+
Interface::Delete(this->g_pVphysics);
88+
}
89+
90+
VPhysics *vphysics;

src/Modules/VPhysics.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
#include "Interface.hpp"
3+
#include "Module.hpp"
4+
#include "Utils.hpp"
5+
6+
// TODO: Custom fonts
7+
class VPhysics : public Module {
8+
public:
9+
Interface *g_pVphysics = nullptr;
10+
11+
using _GetActiveEnvironmentByIndex = int *(__rescall *)(void *thisptr, int index);
12+
_GetActiveEnvironmentByIndex GetActiveEnvironmentByIndex = nullptr;
13+
14+
using _DestroyEnvironment = void(__rescall *)(void *thisptr, void *env);
15+
_DestroyEnvironment DestroyEnvironment = nullptr;
16+
17+
public:
18+
int *GetActivePhysicsEnvironmentByIndex(int index);
19+
void DestroyPhysicsEnvironment(int *env);
20+
21+
bool Init() override;
22+
void Shutdown() override;
23+
const char *Name() override { return MODULE("vphysics"); }
24+
};
25+
26+
extern VPhysics *vphysics;

src/Offsets/INFRA 6905.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ SIGSCAN_WINDOWS(CheckStuck_FloatTime, "FF 15 ? ? ? ? D9 5D ? 8B 4E")
122122
SIGSCAN_EMPTY(FloorReportalBranch)
123123

124124

125+
// VPhysics
126+
OFFSET_WINDOWS(DestroyEnvironment, 9)
127+
OFFSET_WINDOWS(GetActiveEnvironmentByIndex, 10)
128+
129+
125130
// Steam API
126131
SIGSCAN_WINDOWS(interfaceMgrSig, "83 3D ? ? ? ? 00 74 ? B0 01")
127132
OFFSET_WINDOWS(interfaceMgrOff, 2)

src/Offsets/Portal 2 9568.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,11 @@ SIGSCAN_DEFAULT(FloorReportalBranch, "75 7D 8B 8E C0 04 00 00",
511511
"75 ? 8B 85 ? ? ? ? 8B 0D") // "Portal.open_red" xref(nothing after if) -> CProp_Portal::NewLocation -> first function call CPortal_Base2D::NewLocation -> 4x func call followed by test, [jnz]
512512

513513

514+
// VPhysics
515+
OFFSET_EMPTY(DestroyEnvironment)
516+
OFFSET_EMPTY(GetActiveEnvironmentByIndex)
517+
518+
514519
// Steam API
515520
SIGSCAN_DEFAULT(interfaceMgrSig, "89 0D ? ? ? ? 85 C9 0F", "")
516521
OFFSET_DEFAULT(interfaceMgrOff, 2, -1)

src/SAR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ bool SAR::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerF
9999
this->modules->AddModule<FileSystem>(&fileSystem);
100100
this->modules->AddModule<Matchmaking>(&matchmaking);
101101
this->modules->AddModule<SteamAPI>(&steam);
102+
this->modules->AddModule<VPhysics>(&vphysics);
102103
this->modules->InitAll();
103104

104105
SarInitHandler::RunAll();

0 commit comments

Comments
 (0)