core,internet,lte: Prevent calling ConstructSelf in constructors of Object-derived classes

This commit is contained in:
Stefano Avallone
2025-08-21 17:51:47 +02:00
committed by Tom Henderson
parent 736aeddc7f
commit 9eee8a345a
10 changed files with 64 additions and 16 deletions

View File

@@ -83,6 +83,19 @@ ObjectBase::ConstructSelf(const AttributeConstructionList& attributes)
// loop over the inheritance tree back to the Object base class.
NS_LOG_FUNCTION(this << &attributes);
TypeId tid = GetInstanceTypeId();
TypeId objectTid;
// the TypeId of a class derived from Object is initialized to "ns3::Object"; for a class
// deriving from Object, check that this function is called after that the correct TypeId is set
// to ensure that the attributes of the class are initialized
NS_ABORT_MSG_IF(TypeId::LookupByNameFailSafe("ns3::Object", &objectTid) && tid == objectTid,
"ObjectBase::ConstructSelf() has been called on an object of a class derived "
"from the Object class, but the TypeId is still set to ns3::Object.\n"
"This is known to happen in two cases:\n"
"- ObjectBase::ConstructSelf() is called in the class constructor; in this "
"case, override ObjectBase::NotifyConstructionCompleted() to access the "
"initial values of the object attributes as soon as object construction is "
"completed (see issue #1249)\n"
"- the class deriving from Object does not define a static GetTypeId() method");
do // Do this tid and all parents
{
// loop over all attributes in object type

View File

@@ -63,12 +63,13 @@ RttEstimator::RttEstimator()
: m_nSamples(0)
{
NS_LOG_FUNCTION(this);
}
// We need attributes initialized here, not later, so use the
// ConstructSelf() technique documented in the manual
ObjectBase::ConstructSelf(AttributeConstructionList());
void
RttEstimator::NotifyConstructionCompleted()
{
NS_LOG_FUNCTION(this);
m_estimatedRtt = m_initialEstimatedRtt;
m_estimatedVariation = Time(0);
NS_LOG_DEBUG("Initialize m_estimatedRtt to " << m_estimatedRtt.GetSeconds() << " sec.");
}

View File

@@ -89,6 +89,8 @@ class RttEstimator : public Object
Time m_initialEstimatedRtt; //!< Initial RTT estimation
protected:
void NotifyConstructionCompleted() override;
Time m_estimatedRtt; //!< Current estimate
Time m_estimatedVariation; //!< Current estimate variation
uint32_t m_nSamples; //!< Number of samples

View File

@@ -31,8 +31,14 @@ EmuEpcHelper::EmuEpcHelper()
: NoBackhaulEpcHelper()
{
NS_LOG_FUNCTION(this);
// To access the attribute value within the constructor
ObjectBase::ConstructSelf(AttributeConstructionList());
}
void
EmuEpcHelper::NotifyConstructionCompleted()
{
NoBackhaulEpcHelper::NotifyConstructionCompleted();
NS_LOG_FUNCTION(this);
// Create EmuFdNetDevice for SGW
EmuFdNetDeviceHelper emu;

View File

@@ -55,6 +55,9 @@ class EmuEpcHelper : public NoBackhaulEpcHelper
std::vector<uint16_t> cellIds) override;
void AddX2Interface(Ptr<Node> enbNode1, Ptr<Node> enbNode2) override;
protected:
void NotifyConstructionCompleted() override;
private:
/**
* helper to assign addresses to S1-U NetDevices

View File

@@ -45,8 +45,12 @@ NoBackhaulEpcHelper::NoBackhaulEpcHelper()
m_s5LinkMtu(3000)
{
NS_LOG_FUNCTION(this);
// To access the attribute value within the constructor
ObjectBase::ConstructSelf(AttributeConstructionList());
}
void
NoBackhaulEpcHelper::NotifyConstructionCompleted()
{
EpcHelper::NotifyConstructionCompleted();
int retval;

View File

@@ -76,6 +76,8 @@ class NoBackhaulEpcHelper : public EpcHelper
int64_t AssignStreams(int64_t stream) override;
protected:
void NotifyConstructionCompleted() override;
/**
* @brief DoAddX2Interface: Call AddX2Interface on top of the Enb device pointers
*

View File

@@ -28,8 +28,14 @@ PointToPointEpcHelper::PointToPointEpcHelper()
: NoBackhaulEpcHelper()
{
NS_LOG_FUNCTION(this);
// To access the attribute value within the constructor
ObjectBase::ConstructSelf(AttributeConstructionList());
}
void
PointToPointEpcHelper::NotifyConstructionCompleted()
{
NoBackhaulEpcHelper::NotifyConstructionCompleted();
NS_LOG_FUNCTION(this);
// since we use point-to-point links for the backhaul links,
// we use a /30 subnet which can hold exactly two addresses

View File

@@ -51,6 +51,9 @@ class PointToPointEpcHelper : public NoBackhaulEpcHelper
Ptr<NetDevice> lteEnbNetDevice,
std::vector<uint16_t> cellIds) override;
protected:
void NotifyConstructionCompleted() override;
private:
/**
* S1-U interfaces