簡體   English   中英

Valgrind 中的內存泄漏使用 new

[英]Memory leak in Valgrind using new

這個例子可能很糟糕,但這是我跟蹤 Valgrind 顯示的堆棧幀時的樣子。 LocationList、Location、FolderList 和 Folder 是不同的類,我只粘貼了這些類的復制構造函數和賦值運算符。 但我不確定為什么會出現內存泄漏。

我知道我在復制構造函數中使用了 new 運算符和 for 循環,這可能是導致問題的原因,但我不確定如何處理。 這是來自 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)

下面是代碼棧:

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             }

看起來您有很多泄漏( loss record 28 of 1,002 )。

首先,一件小事。 在 C++ 中,您不需要在刪除指針之前檢查指針是否為非 NULL。 所以

if (folders)
    delete [] folders;

可以替換為

delete [] folders;

接下來,你說你不能使用智能指針。 如果您可以使用標准庫容器,那就更好了。

因此,而不是將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];

你可以定義std::vector<Folder> folders; (而不是Folder* folders;這是我認為你目前擁有的)並寫

folders = list.folders;

這樣做的其他好處:

  1. 您無需管理向量的內存。
  2. 不需要 curr_size 和 cur_capacity - std::vector 提供了這些

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM