0

I have the next dynamic allocation memory.

//before

RMIUpStream *rmiUpStream = RMIUpStream::create("RMIResources");

//after

boost::shared_ptr<RMIUpStream> rmiUpStream(RMIUpStream::create("RMIResources"));

//create function

RMIUpStream* RMIUpStream::create(const std::string& rmiResourceString)
{
  RMIUpStream* rmiUpStream = nullptr;

  DEBUG("RMIUpStream::create - ResourceString: "+  rmiResourceString);

  try {
    FileInputStream inCfg(SpecificBoundaryBasics::FILE_NAME_STRING);
    XML::Reader reader(inCfg);

    bool resourcesFound = false;

    while ((reader.getEventType() != XML::Reader::END_DOCUMENT) and (not resourcesFound)) {
      if (reader.getEventType() == XML::Reader::START_TAG) {
        if (reader.getName() == rmiResourceString) {
          resourcesFound = true;
        }
      }
      reader.nextEventType();
    }

    if (resourcesFound) {
      rmiUpStream = new RMIUpStream(rmiResourceString);
      boost::shared_ptr<GeneralRACOONStack::RACOONStackDownStreamBundle> downStreamBundle(
              GeneralRACOONStack::RACOONStackDownStreamBundle::create(*rmiUpStream, rmiResourceString));
      rmiUpStream->setDownStreamBundle(downStreamBundle);
    }
    else {
      throw XML::ValidityViolation("Could not found " + rmiResourceString, reader.getLineNumber());
    }
  }
  catch (XML::Violation& violation) {
    throw ErrorTypes::ResourceError(Outputs::FileParameters(std::string("RMIUpStream.") + SpecificBoundaryBasics::FILE_NAME_STRING,
                                                         violation.getLineNumber(),
                                                         violation.getDetail()));
  }

  return rmiUpStream;
}

I expect that the allocation of raw pointer in smart pointer will change the errors from valgrind.txt to disappear, but not.

//valgrind.txt

==20363== 32,640 bytes in 1 blocks are possibly lost in loss record 2,403 of 2,406
==20363==    at 0x4028F03: malloc (vg_replace_malloc.c:298)
==20363==    by 0x40C968C: ??? (in /lib/libc-2.9.so)
==20363==    by 0x40C903E: iconv_open (in /lib/libc-2.9.so)
==20363==    by 0x8304484: xercesc_3_1::IconvGNUTransService::IconvGNUTransService(xercesc_3_1::MemoryManager*) (IconvGNUTransService.cpp:450)
==20363==    by 0x822407A: xercesc_3_1::XMLPlatformUtils::makeTransService() (PlatformUtils.cpp:483)
==20363==    by 0x8224391: xercesc_3_1::XMLPlatformUtils::Initialize(char const*, char const*, xercesc_3_1::PanicHandler*, xercesc_3_1::MemoryManager*) (PlatformUtils.cpp:271)
==20363==    by 0x80F77AA: RMIUpStream::RMIUpStream(std::string) (RMIUpStream.cpp:98)
==20363==    by 0x80F80CD: RMIUpStream::create(std::string const&) (RMIUpStream.cpp:68)
==20363==    by 0x810CC8E: main (main.cpp:171)

This is just one of many logos of this type. The memory that is possibly lost seems to increase.

Ionut Alexandru
  • 680
  • 5
  • 17
  • hello. memory leaks detection/logs are sometimes hard to read. You might want to try using dr memory (https://drmemory.org/). – Jean-Marc Volle Apr 13 '20 at 09:50
  • In your code it is not clear who takes ownership of rmiUpStream which has been allocated using new operator. If you do not need shared_ptr (only own owner per instanciated class) you would better use std::unique_ptr. This will help you identify owner for each instantiated class. – Jean-Marc Volle Apr 13 '20 at 09:58

1 Answers1

0

Your memory leak warning is probably created by the fact creating a shared pointer can throw. Imagine what happens if there is enough memory to make a RMIUpStream, but not enough to make a shared pointer to hold it. The RMIUpStream object is created, but never tied to an object. This is why make_shared exists

See here for details

---- UPDATE ---

What happens if you don't have make_shared?

Firstly, be aware, this is complex stuff to do by hand, see here. https://herbsutter.com/gotw/_102/

Use library code to do this for you!

But actually your problem can be boiled down to this line of code...

  rmiUpStream = new RMIUpStream(rmiResourceString); // << not exception safe

Unless you put this in a smart pointer (like unique_ptr) then any exception thrown will loose this memory. Simply put this in a boost::unique_ptr

Tiger4Hire
  • 1,065
  • 5
  • 11
  • i have old `boost` version there isn't `make_shared` – Ionut Alexandru Apr 13 '20 at 11:01
  • I would consider updating, boost::make_shared is pretty standard, and has now been replaced by std::make_shared. However, if that is not possible, simply flip you logic, so you create your shared pointer first, then assign it the value of the "new". I will update the example for you – Tiger4Hire Apr 14 '20 at 07:04