我有两种类型的Ll2TxPacketBds和Ll2TxLbPacketBds,后一类继承自前面定义的类,如下所示:
class Ll2TxPacketBds
{
public:
Ll2TxPacketBds(MainCorePfDrv *pCorePfDrv, const MainEthTxPacketDesc &pktDesc, uint32 pktProd);
Ll2TxPacketBds(Ll2TxPacketBds&& moveFrom); //Move Constructor
~Ll2TxPacketBds();
virtual core_tx_bd_union bd(uint8 nSge, uint32 pktProd);
uint8 sglSize() const;
protected:
MainEthTxPacketDesc m_pktDesc;
vector<shared_ptr<DrvBuf>> m_vectDrvBuf;
uint8 m_txDst; // diffrent bd for loop back packet
};
class Ll2TxLbPacketBds : public Ll2TxPacketBds
{
public:
Ll2TxLbPacketBds(MainCorePfDrv *pCorePfDrv, const MainEthTxPacketDesc &pktDesc, uint32 pktProd) : Ll2TxPacketBds(pCorePfDrv, pktDesc, pktProd) {};
Ll2TxLbPacketBds(Ll2TxLbPacketBds&& moveFrom) : Ll2TxPacketBds((Ll2TxPacketBds&&)moveFrom) {};
~Ll2TxLbPacketBds() { Ll2TxPacketBds::~Ll2TxPacketBds(); };
core_tx_bd_union bd(uint8 nSge, uint32 pktProd);
};
你可以看到son类重新实现了虚拟bd方法。 有一个父指针类型的队列定义如下:
deque<Ll2TxPacketBds*> m_txPacketList;
使用两种不同的方法将元素推入deque中,如下所示:
1
Ll2TxPacketBds* bd = (m_txDest != CORE_TX_DEST_LB) ? &Ll2TxPacketBds(m_pCorePfDrv, *pPktDesc, m_pktProd) : &Ll2TxLbPacketBds(m_pCorePfDrv, *pPktDesc, m_pktProd);
m_txPacketList.push_back(bd); // Polymorphism/virtual function not working here
2
if (m_txDest != CORE_TX_DEST_LB)
{
Ll2TxPacketBds* bd = &Ll2TxPacketBds(m_pCorePfDrv, *pPktDesc, m_pktProd);
m_txPacketList.push_back(bd);
}
else
{
Ll2TxLbPacketBds* bdLb = &Ll2TxLbPacketBds(m_pCorePfDrv, *pPktDesc, m_pktProd);
m_txPacketList.push_back(bdLb); //Works here
}
弹出元素后,调用bd()如下:
m_pBdRing->peekProd() = m_txPacketList.back()->bd(nBd, m_pktProd);
使用调试器我确实在#1和#2中看到正确的构造函数被调用...
如果popped元素是由方法#1创建的,那么多态性将不会发生,并且Ll2TxPacketBds实现bd(..)将始终被调用,而方法#2按预期工作,就多态性而言。
答案 0 :(得分:6)
您不能获取堆栈分配对象的基指针,因为它会被销毁,而您只剩下指向不再存在的对象基础部分的指针。所以它实际上是未定义的行为,因为该对象不再存在,它只是运气(有时),这正是UB通常表现出来的。
解决方案是替换:
Ll2TxPacketBds* bd = &Ll2TxPacketBds(m_pCorePfDrv, *pPktDesc, m_pktProd);
与
Ll2TxPacketBds* bd = new Ll2TxPacketBds(m_pCorePfDrv, *pPktDesc, m_pktProd);
然后释放您保存在容器中的内容。为此,您还需要将析构函数设置为虚拟化!
您可以将其设置为智能指针,这将节省您的释放,但您仍然需要虚拟析构函数(即使在基类中为空)。