Bugzilla – Bug 2081
Segmentation fault caused by unwanted Ptr<Packet> dealocation
Last modified: 2019-11-04 20:21:24 EST
Sorry but is not possible for me to provide a code in order to reproduce the error since is a new module. I am using a function (WHartNetDevice::ProduceInfo()) that Enqueue two different packets in a buffer. Those packets are created by a factory class (WHartPacketFactory::GerateDataPacket) and returned to the ProduceInfo Function like the code: //----------- Inside Produce info void WHartNetDevice::ProduceInfo(void) { uint8_t a=7; Mac64Address to = Mac64Address::ConvertFrom (m_phy->GetChannel()->GetWHartDevice(gatewayMainRoute)->GetAddress()); uint8_t* temp; temp = &a; m_phy->GetChannel()->GetWHartDevice(gatewayMainRoute)->GetAddress().CopyTo(temp); uint64_t destAddr = ConvertAddressToInt64 (temp); uint8_t* temp2; temp2 = &a; m_address.CopyTo(temp2); uint64_t sourceAddr = ConvertAddressToInt64 (temp2); Ptr<Packet> mygpacket = factory->GenerateDataPacket(this, DATA_PACKET, PUBLIC, NORMAL, S_NICK_D_NICK, sourceAddr, destAddr, m_phy->GetChannel()->GetDevicePhyIndex(m_address),m_phy->GetChannel()->GetDevicePhyIndex(to), 0); EnqueuePacket( mygpacket,2,m_phy->GetChannel()->GetWHartDevice(gatewayMainRoute)->GetAddress(),2,GetLinkId(GetPhyIndex(),GetPhyIndex(),gatewayMainRoute ) ); uint8_t* temp3; temp3 = &a; if(gatewayAlternateRoute!=-1){ m_phy->GetChannel()->GetWHartDevice(gatewayAlternateRoute)->GetAddress().CopyTo(temp3); uint64_t alternateDestAddr = ConvertAddressToInt64 (temp3); Ptr<Packet> mygAlternatePacket = factory->GenerateDataPacket(this, DATA_PACKET, PUBLIC, NORMAL, S_NICK_D_NICK, sourceAddr, alternateDestAddr, m_phy->GetChannel()->GetDevicePhyIndex(m_address),m_phy->GetChannel()->GetDevicePhyIndex(Mac64Address::ConvertFrom (m_phy->GetChannel()->GetWHartDevice(gatewayAlternateRoute)->GetAddress()) ), 0); EnqueuePacket( mygAlternatePacket,1,m_phy->GetChannel()->GetWHartDevice(gatewayAlternateRoute)->GetAddress(),2, GetLinkId(GetPhyIndex(),GetPhyIndex(),gatewayAlternateRoute) ); } } //------------Inside the packet factory Ptr<Packet> WHartPacketFactory::GenerateDataPacket (Ptr<WHartNetDevice> sender,enum PacketType type, enum NetworkKey key,enum PacketPriority priority, enum AddrSpec addspec, uint64_t addfrom, uint64_t addto, uint32_t fromnick,uint32_t tonick, uint32_t final_dest) { Ptr<Packet> packet = Create<Packet>(90); WhartMacHeader wh; wh.SetPacketType(type); wh.SetAddrSpec(addspec); switch (addspec) { case S_NICK_D_NICK: wh.SetDestAddr(tonick); wh.SetSourceAddr(fromnick); break; case S_NICK_D_EUI64: wh.SetSourceAddr(fromnick); wh.SetDestAddrEUI64(addto); break; case S_EUI64_D_NICK: wh.SetSourceAddrEUI64(addfrom); wh.SetDestAddr(tonick); break; case S_EUI64_D_EUI64: wh.SetSourceAddrEUI64(addfrom); wh.SetDestAddrEUI64(addto); break; } wh.SetNetworkKey(key); wh.SetPacketPriority (priority); packet->AddHeader(wh); WHartPacketFactory::PacketLog log; log.DepartureTime = Simulator::Now(); log.final_destination = final_dest; log.payload = 50; log.completedTransmission = false; WhartTag tag; tag.SetSourceIndex (fromnick); tag.SetDestIndex (tonick); tag.SetFinalDestIndex (final_dest); tag.SetInitialSourceIndex (sender->GetPhyIndex()); packet->AddPacketTag (tag); return packet; } //Buffer Cration and function to add packets to the buffer inside (class WHartNetDevice) struct BufferItem { uint16_t protocolNumber; Address dest; Ptr<Packet> p; uint ttl; int destIndex; int link_id; }; typedef std::vector< WHartNetDevice::BufferItem > PktBuffer; WHartNetDevice::PktBuffer MainBuffer; uint8_t WHartNetDevice::EnqueuePacket(Ptr<Packet> p, uint8_t num, const Address dest, uint16_t protocolNumber, uint64_t link_id) { struct BufferItem temp; temp.p = p; temp.ttl=num; temp.dest=dest; temp.protocolNumber = protocolNumber; temp.link_id = link_id; Mac64Address to = Mac64Address::ConvertFrom (dest); temp.destIndex = m_phy->GetChannel()->GetDevicePhyIndex(to); MainBuffer.push_back(temp); return 1; } At the end i got an Segmentation fault as decribed in the valgrind log. ==14914== Invalid read of size 4 ==14914== at 0x412D36: ns3::SimpleRefCount<ns3::Packet, ns3::empty, ns3::DefaultDeleter<ns3::Packet> >::Unref() const (simple-ref-count.h:112) ==14914== by 0x4112EA: ns3::Ptr<ns3::Packet>::~Ptr() (ptr.h:757) ==14914== by 0xAE2B43F: ns3::WHartNetDevice::ProduceInfo() (whart-net-device.cc:1270) ==14914== by 0x40B7A8: CallProduceInfo(ns3::Ptr<ns3::Node>) (sectest.cc:58) ==14914== by 0x412A5A: ns3::EventImpl* ns3::MakeEvent<ns3::Ptr<ns3::Node>, ns3::Ptr<ns3::Node> >(void (*)(ns3::Ptr<ns3::Node>), ns3::Ptr<ns3::Node>)::EventFunctionImpl1::Notify() (make-event.h:524) ==14914== by 0xC906C32: ns3::EventImpl::Invoke() (event-impl.cc:51) ==14914== by 0xC90B75F: ns3::DefaultSimulatorImpl::ProcessOneEvent() (default-simulator-impl.cc:140) ==14914== by 0xC90BAD9: ns3::DefaultSimulatorImpl::Run() (default-simulator-impl.cc:193) ==14914== by 0xC907969: ns3::Simulator::Run() (simulator.cc:204) ==14914== by 0x40F596: RunSimulation() (sectest.cc:330) ==14914== by 0x40FEA4: main (sectest.cc:339) ==14914== Address 0x2000000000000 is not stack'd, malloc'd or (recently) free'd ==14914== ==14914== ==14914== Process terminating with default action of signal 11 (SIGSEGV) ==14914== General Protection Fault ==14914== at 0x412D36: ns3::SimpleRefCount<ns3::Packet, ns3::empty, ns3::DefaultDeleter<ns3::Packet> >::Unref() const (simple-ref-count.h:112) ==14914== by 0x4112EA: ns3::Ptr<ns3::Packet>::~Ptr() (ptr.h:757) ==14914== by 0xAE2B43F: ns3::WHartNetDevice::ProduceInfo() (whart-net-device.cc:1270) ==14914== by 0x40B7A8: CallProduceInfo(ns3::Ptr<ns3::Node>) (sectest.cc:58) ==14914== by 0x412A5A: ns3::EventImpl* ns3::MakeEvent<ns3::Ptr<ns3::Node>, ns3::Ptr<ns3::Node> >(void (*)(ns3::Ptr<ns3::Node>), ns3::Ptr<ns3::Node>)::EventFunctionImpl1::Notify() (make-event.h:524) ==14914== by 0xC906C32: ns3::EventImpl::Invoke() (event-impl.cc:51) ==14914== by 0xC90B75F: ns3::DefaultSimulatorImpl::ProcessOneEvent() (default-simulator-impl.cc:140) ==14914== by 0xC90BAD9: ns3::DefaultSimulatorImpl::Run() (default-simulator-impl.cc:193) ==14914== by 0xC907969: ns3::Simulator::Run() (simulator.cc:204) ==14914== by 0x40F596: RunSimulation() (sectest.cc:330) ==14914== by 0x40FEA4: main (sectest.cc:339) desalocating m_ptr: 0x2000000000000==14914== ==14914== HEAP SUMMARY: ==14914== in use at exit: 1,626,617 bytes in 22,486 blocks ==14914== total heap usage: 46,156 allocs, 23,670 frees, 3,502,788 bytes allocated ==14914== ==14914== LEAK SUMMARY: ==14914== definitely lost: 0 bytes in 0 blocks ==14914== indirectly lost: 0 bytes in 0 blocks ==14914== possibly lost: 320,155 bytes in 6,057 blocks ==14914== still reachable: 1,306,462 bytes in 16,429 blocks ==14914== suppressed: 0 bytes in 0 blocks ==14914== Rerun with --leak-check=full to see details of leaked memory ==14914== ==14914== For counts of detected and suppressed errors, rerun with: -v ==14914== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) Command ['valgrind', '/home/marcelo/ns3/ns-allinone-3.22/ns-3.22/build/scratch/sectest'] terminated with signal SIGSEGV. Run it under a debugger to get more information (./waf --run <program> --command-template="gdb --args %s <args>"). ------- My uderststanding is that the ns-3 is dealocating the Ptr<Packet> in the end of the function leading to the segmentation fault. Is there a way to prevent such dealocation to occur? Thanks for the patience Marcelo Nobre
Obviously, Ptr<> smart pointer class is responsible for avoiding such problems. I checked the code attached and I see no obvious problem in how you use the Ptr<Packet> API. (You are not calling PeekPointer anywhere, right ?) Maybe you should add some debugging output to the packet object destructor/unref method to check if you are indeed calling unref on an object that has been deleted already.
Look at me still talking when there's science to do uint8_t a=7; Mac64Address to = Mac64Address::ConvertFrom (m_phy->GetChannel()->GetWHartDevice(gatewayMainRoute)->GetAddress()); uint8_t* temp; temp = &a; m_phy->GetChannel()->GetWHartDevice(gatewayMainRoute)->GetAddress().CopyTo(temp); uint64_t destAddr = ConvertAddressToInt64 (temp); I love the smell of memory bugs in the morning. Why are you trying to squeeze a Mac64 into a uint8_t ? You know, initialising it to "7" isn't helping a lot. It doesn't hurt, and according to this old "Friends" episode (https://www.youtube.com/watch?v=mdK6LVDI3kg), it *does* make sense to use 7... but still, it doesn't do more than initialising it to 42. Cheers.
Any further info ? Can we close this bug ?
Tommaso seems to have identified the issue in Marcelo's code.