Утечка памяти в Valgrind с использованием нового - PullRequest
1 голос
/ 29 января 2020

Пример может быть плохим, но именно так он выглядит, когда я отслеживаю кадр стека, который показывает Valgrind. LocationList, Location, FolderList и Folder - это разные классы, и я вставил только конструкторы копирования и операторы присваивания этих классов. Но я не уверен, почему происходит утечка памяти.

Я понимаю, что я использую оператор new и a для l oop в конструкторе копирования, что может быть причиной проблемы, но я не уверен, как с этим справиться. Вот стек вызовов от 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             }

1 Ответ

0 голосов
/ 30 января 2020

Похоже, у вас много утечек (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 предоставляет эти
...