17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 09:49:19 +02:00

Disown the vehicles before deleting their driver.

TDynamicObject::Update() reads ctOwner->Controlling() every frame, but ctOwner is
only ever refreshed by CheckVehicles() and cleared only by Dettach(). Both
TController::MoveTo() and ~TDynamicObject() delete a controller while the rest of
the consist still points at it, so the vehicles keep dereferencing freed memory
until some other driver happens to claim them.

Seen as a segfault in DynObj.cpp on ctOwner->Controlling()->MainCtrlPosNo after
changing cabs through an EN57 with an AI driver in the leading unit: ctOwner was
a live-looking pointer into a freed TController, its mvControlling long gone.

~TController() now clears ctOwner on every vehicle still pointing at it. nullptr
is what the readers already expect - they fall back on Mechanik or skip the block
- and the next CheckVehicles() re-establishes ownership.
This commit is contained in:
maj00r
2026-09-06 13:48:05 +02:00
parent aaccd7b9b7
commit e95d4a57bc

View File

@@ -1999,6 +1999,19 @@ void TController::CloseLog()
TController::~TController()
{ // wykopanie mechanika z roboty
// ctOwner is refreshed only by CheckVehicles(), so a vehicle left pointing at a deleted driver
// keeps being dereferenced every frame until some other one claims it. Disown them here, as
// MoveTo() and ~TDynamicObject() both delete a controller out from under a live consist.
// nullptr is expected by the readers, which fall back on Mechanik or skip the block outright
if( simulation::is_ready
&& false == Global.applicationQuitOrder ) {
for( auto *vehicle : simulation::Vehicles.sequence() ) {
if( vehicle != nullptr
&& vehicle->ctOwner == this ) {
vehicle->ctOwner = nullptr;
}
}
}
CloseLog();
};