Bug 2081 - Segmentation fault caused by unwanted Ptr<Packet> dealocation
Segmentation fault caused by unwanted Ptr<Packet> dealocation
Status: RESOLVED INVALID
Product: ns-3
Classification: Unclassified
Component: core
ns-3.22
PC Linux
: P5 normal
Assigned To: Mathieu Lacage
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2015-03-18 20:33 EDT by Marcelo
Modified: 2019-11-04 20:21 EST (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marcelo 2015-03-18 20:33:51 EDT
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
Comment 1 Mathieu Lacage 2015-03-19 03:09:04 EDT
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.
Comment 2 Tommaso Pecorella 2015-03-19 18:33:55 EDT
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.
Comment 3 Tommaso Pecorella 2015-03-28 05:01:38 EDT
Any further info ?
Can we close this bug ?
Comment 4 Peter Barnes 2019-11-04 18:24:51 EST
Tommaso seems to have identified the issue in Marcelo's code.