简体   繁体   English

Valgrind 中的内存泄漏使用 new

[英]Memory leak in Valgrind using new

The example may be bad but this is how it looks when I trace the stack frame which Valgrind shows.这个例子可能很糟糕,但这是我跟踪 Valgrind 显示的堆栈帧时的样子。 The LocationList, Location, FolderList and Folder are different classes and I have pasted only the copy constructors and assignment operators of these classes. LocationList、Location、FolderList 和 Folder 是不同的类,我只粘贴了这些类的复制构造函数和赋值运算符。 But I am unsure why there is a memory leak.但我不确定为什么会出现内存泄漏。

I understand that I am using new operator and a for loop in copy constructor which could be the cause of trouble but I am unsure how to handle this.我知道我在复制构造函数中使用了 new 运算符和 for 循环,这可能是导致问题的原因,但我不确定如何处理。 Here is the call stack from Valgrind.这是来自 Valgrind 的调用堆栈。

==15733== 8 bytes in 1 blocks are definitely lost in loss record 28 of 1,002
==15733==    at 0x4A07152: operator new[](unsigned long) (vg_replace_malloc.c:363)
==15733==    by 0x54FA25: FolderList::operator=(FolderList const&) (Folder.h:63)
==15733==    by 0x54FD8A: Server::operator=(Server const&) (Server.h:22)
==15733==    by 0x550631: Location::operator=(Location const&) (Location.h:44)
==15733==    by 0x5507AC: LocationList::LocationList(LocationList const&) (Location.h:76)
==15733==    by 0x54988C: VPSyncInterface::login(std::string, std::string, VPStatus*) (vpsync.cc:365)
==15733==    by 0x549AD5: VPSyncInterface::connect(std::string, std::string, VPStatus*) (vpsync.cc:382)
==15733==    by 0x548FF0: VPSyncInterface::reconnect(VPStatus*) (vpsync.cc:227)
==15733==    by 0x548D39: VPSyncInterface::initialize(VPStatus*, int) (vpsync.cc:175)
==15733==    by 0x42E5B4: ProcessImageImpl::ProcessImageImpl(char const*, int, char const*, int) (ProcessImageImpl.cc:172)
==15733==    by 0x426FDD: cvRetrievalImpl::getProcessObject(cvRetrieval::ProcessType, char const*, int, char const*, int) (cvRetrievalImpl.cc:70)
==15733==    by 0x426B4A: main (ThinIMAGEd.cc:727)

Below is the code stack:下面是代码栈:

cvRetrievalImpl.cc
    69   case cvRetrieval::PROCESS_IMAGE:
    70     return new ProcessImageImpl (application_class, instance_wants_to_access_vp, auth_group, threadCount);
    71     break;

ProcessImageImpl.cc

    VPStatus init_status;
    if (syncInterface->initialize (&init_status) != 0)
    {
        cvLog (CV_LOG_FATAL, "Cannot initialize VP sync interface: %s", 
                    init_status.interpret_current_status());
         exit (EXIT_FAILURE);
    }        

vpsync.cc            
    364     LogonXMLParser* parser = new LogonXMLParser ();
    365     AddDtd *aDtd = new AddDtd (application_class);
    366     string logonOutputXML = aDtd->add (out_xml, process);
    367    
    368     LocationList *vp_locations;
    369     vp_locations = parser->doParse ((const XMLByte*) logonOutputXML.c_str (), logonOutputXML.size ());
    370     delete aDtd;

    378     if (locations)
    379         delete locations;
    380     // We have to make a private copy of the locations returned by the parser,
    381     // because the parser's copy will disappear when the parser is destroyed.
    382     locations = new LocationList (*vp_locations);
    383     delete parser;


LocationList& operator= (const LocationList& list)
    79             {
    80             if (this == &list)
    81                 return *this;
    82             incr = list.incr;
    83             curr_size = list.curr_size;
    84             curr_capacity = list.curr_capacity;
    85             if (locations)
    86                 delete [] locations;
    87             locations = new Location[curr_capacity];
    88             for (unsigned int i = 0; i < curr_size; i++)
    89                 locations[i] = list.locations[i];
    90             return *this;
    91             }

Location.h
    39         Location& operator= (const Location& location)
    40             {
    41             if (this == &location)
    42                 return *this;
    43             locationName = location.locationName;
    44             server = location.server;
    45             servers = location.servers;
    46             return *this;
    47             }

Server.h
    16         Server& operator= (const Server& server)
    17             {
    18             if (this == &server)
    19                 return *this;
    20             serverName = server.serverName;
    21             folder = server.folder;
    22             folders = server.folders;
    23             return *this;
    24             }

Folder.h

    54         FolderList& operator= (const FolderList& list)
    55             {
    56             if (this == &list)
    57                 return *this;
    58             incr = list.incr;
    59             curr_size = list.curr_size;
    60             curr_capacity = list.curr_capacity;
    61             if (folders)
    62                 delete [] folders;
    63             folders = new Folder[curr_capacity];
    64             for (unsigned int i = 0; i < curr_size; i++)
    65                 folders[i] = list.folders[i];
    66             return *this;
    67             }

    16         Folder& operator= (const Folder& folder)
    17             {
    18             if (this == &folder)
    19                 return *this;
    20             folderName = folder.folderName;
    21             folderDesc = folder.folderDesc;
    22             return *this;
    23             }

It looks like you have many leaks ( loss record 28 of 1,002 ).看起来您有很多泄漏( loss record 28 of 1,002 )。

First, a minor thing.首先,一件小事。 In C++ you don't need to check that a pointer is non-NULL before deleting it.在 C++ 中,您不需要在删除指针之前检查指针是否为非 NULL。 So所以

if (folders)
    delete [] folders;

can be replaced by可以替换为

delete [] folders;

Next, you say that you can't use smart pointers.接下来,你说你不能使用智能指针。 It would be even better if you could use standard library containers.如果您可以使用标准库容器,那就更好了。

So instead of defining folders as a pointer to Folder and writing因此,而不是将folders定义为指向Folder的指针并写入

if (folders)
   delete [] folders;
folders = new Folder[curr_capacity];
for (unsigned int i = 0; i < curr_size; i++)
    folders[i] = list.folders[i];

you could define std::vector<Folder> folders;你可以定义std::vector<Folder> folders; (instead of Folder* folders; which is what I presume you have currently) and write (而不是Folder* folders;这是我认为你目前拥有的)并写

folders = list.folders;

Other benefits of this:这样做的其他好处:

  1. No need for you to manage the vector's memory.您无需管理向量的内存。
  2. No need for curr_size and cur_capacity - std::vector provides these不需要 curr_size 和 cur_capacity - std::vector 提供了这些

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM