Date:2015-04-23 21:07:33 (5 years 1 month ago)
Author:Maarten ter Huurne
Commit:7eb377a8578d44365073179c54e6ee155cb73f33
Message:Keep track of Link objects using unique_ptr

This ensures the memory is freed when the pointers are removed. While
there was an explicit delete loop in the destructor, memory leaks could
occur when links were removed from the menu.
Files: src/menu.cpp (16 diffs)
src/menu.h (3 diffs)

Change Details

src/menu.cpp
104104    btnContextMenu.setPosition(gmenu2x.resX - 38, gmenu2x.bottomBarIconY);
105105}
106106
107Menu::~Menu() {
108    freeLinks();
107Menu::~Menu()
108{
109109}
110110
111111void Menu::readSections(std::string const& parentDir)
...... 
151151    linkRows = (gmenu2x.resY - 35 - skinConfInt["topBarHeight"]) / skinConfInt["linkHeight"];
152152
153153    //reload section icons
154    vector<string>::size_type i = 0;
155    for (string sectionName : sections) {
154    decltype(links)::size_type i = 0;
155    for (auto& sectionName : sections) {
156156        gmenu2x.sc["skin:sections/" + sectionName + ".png"];
157157
158        for (Link *&link : links[i]) {
158        for (auto& link : links[i]) {
159159            link->loadIcon();
160160        }
161161
...... 
233233    sc.skinRes("imgs/section-l.png")->blit(s, 0, 0);
234234    sc.skinRes("imgs/section-r.png")->blit(s, width - 10, 0);
235235
236    vector<Link*> &sectionLinks = links[iSection];
237    const uint numLinks = sectionLinks.size();
236    auto& sectionLinks = links[iSection];
237    auto numLinks = sectionLinks.size();
238238    gmenu2x.drawScrollBar(
239239            linkRows, (numLinks + linkColumns - 1) / linkColumns, iFirstDispRow);
240240
...... 
353353/*====================================
354354   SECTION MANAGEMENT
355355  ====================================*/
356void Menu::freeLinks() {
357    for (vector< vector<Link*> >::iterator section = links.begin(); section<links.end(); section++)
358        for (vector<Link*>::iterator link = section->begin(); link<section->end(); link++)
359            delete *link;
360}
361356
362vector<Link*> *Menu::sectionLinks(int i) {
363    if (i<0 || i>=(int)links.size())
357vector<unique_ptr<Link>> *Menu::sectionLinks(int i)
358{
359    if (i<0 || i>=(int)links.size()) {
364360        i = selSectionIndex();
361    }
365362
366    if (i<0 || i>=(int)links.size())
367        return NULL;
363    if (i<0 || i>=(int)links.size()) {
364        return nullptr;
365    }
368366
369367    return &links[i];
370368}
...... 
417415        link->setIcon(icon);
418416    }
419417
420    links[section].push_back(link);
418    links[section].emplace_back(link);
421419}
422420
423421bool Menu::addLink(string const& path, string const& file)
...... 
501499        auto idx = sectionNamed(sectionName);
502500        auto link = new LinkApp(gmenu2x, linkpath, true);
503501        link->setSize(gmenu2x.skinConfInt["linkWidth"], gmenu2x.skinConfInt["linkHeight"]);
504        links[idx].push_back(link);
502        links[idx].emplace_back(link);
505503    } else {
506504
507505        ERROR("Error while opening the file '%s' for write.\n", linkpath.c_str());
...... 
525523
526524void Menu::deleteSelectedLink()
527525{
528    bool icon_used = false;
529526    string iconpath = selLink()->getIconPath();
530527
531528    INFO("Deleting link '%s'\n", selLink()->getTitle().c_str());
...... 
535532    sectionLinks()->erase( sectionLinks()->begin() + selLinkIndex() );
536533    setLinkIndex(selLinkIndex());
537534
538    for (vector< vector<Link*> >::iterator section = links.begin();
539                !icon_used && section<links.end(); section++)
540        for (vector<Link*>::iterator link = section->begin();
541                    !icon_used && link<section->end(); link++)
542            icon_used = iconpath == (*link)->getIconPath();
543
544    if (!icon_used)
545      gmenu2x.sc.del(iconpath);
535    bool icon_used = false;
536    for (auto& section : links) {
537        for (auto& link : section) {
538            if (iconpath == link->getIconPath()) {
539                icon_used = true;
540            }
541        }
542    }
543    if (!icon_used) {
544        gmenu2x.sc.del(iconpath);
545    }
546546}
547547
548548void Menu::deleteSelectedSection() {
...... 
555555}
556556
557557bool Menu::linkChangeSection(uint linkIndex, uint oldSectionIndex, uint newSectionIndex) {
558    if (oldSectionIndex<sections.size() && newSectionIndex<sections.size() && linkIndex<sectionLinks(oldSectionIndex)->size()) {
559        sectionLinks(newSectionIndex)->push_back( sectionLinks(oldSectionIndex)->at(linkIndex) );
560        sectionLinks(oldSectionIndex)->erase( sectionLinks(oldSectionIndex)->begin()+linkIndex );
561        //Select the same link in the new position
562        setSectionIndex(newSectionIndex);
563        setLinkIndex(sectionLinks(newSectionIndex)->size()-1);
564        return true;
565    }
566    return false;
558    // Fetch sections.
559    auto oldSectionLinks = sectionLinks(oldSectionIndex);
560    if (!oldSectionLinks) return false;
561    auto newSectionLinks = sectionLinks(newSectionIndex);
562    if (!newSectionLinks) return false;
563
564    // Find link in old section.
565    if (linkIndex >= oldSectionLinks->size()) return false;
566    auto it = oldSectionLinks->begin() + linkIndex;
567
568    // Move link.
569    auto link = it->release();
570    oldSectionLinks->erase(it);
571    newSectionLinks->emplace_back(link);
572
573    // Select the same link in the new section.
574    setSectionIndex(newSectionIndex);
575    setLinkIndex(newSectionLinks->size() - 1);
576
577    return true;
567578}
568579
569580void Menu::linkLeft() {
...... 
615626}
616627
617628Link *Menu::selLink() {
618    if (sectionLinks()->size()==0) return NULL;
619    return sectionLinks()->at(iLink);
629    auto curSectionLinks = sectionLinks();
630    if (curSectionLinks->empty()) {
631        return nullptr;
632    } else {
633        return curSectionLinks->at(iLink).get();
634    }
620635}
621636
622637LinkApp *Menu::selLinkApp() {
...... 
705720        link->setSize(gmenu2x.skinConfInt["linkWidth"], gmenu2x.skinConfInt["linkHeight"]);
706721
707722        auto idx = sectionNamed(link->getCategory());
708        links[idx].push_back(link);
723        links[idx].emplace_back(link);
709724    }
710725
711726    opk_close(opk);
...... 
753768 * correspond to an OPK present in the directory. */
754769void Menu::removePackageLink(std::string const& path)
755770{
756    for (vector< vector<Link*> >::iterator section = links.begin();
757                section < links.end(); section++) {
758        for (vector<Link*>::iterator link = section->begin();
759                    link < section->end(); link++) {
760            LinkApp *app = dynamic_cast<LinkApp *> (*link);
771    for (auto section = links.begin(); section != links.end(); ++section) {
772        for (auto link = section->begin(); link != section->end(); ++link) {
773            LinkApp *app = dynamic_cast<LinkApp *>(link->get());
761774            if (!app || !app->isOpk() || app->getOpkFile().empty())
762775                continue;
763776
...... 
766779                            app->getOpkFile().c_str());
767780                section->erase(link);
768781                if (section - links.begin() == iSection
769                            && iLink == (int) section->size())
782                            && iLink == (int) section->size()) {
770783                    setLinkIndex(iLink - 1);
771                link--;
784                }
785                --link;
772786            }
773787        }
774788    }
...... 
783797#endif
784798#endif
785799
786static bool compare_links(Link *a, Link *b)
800static bool compare_links(unique_ptr<Link> const& a, unique_ptr<Link> const& b)
787801{
788    LinkApp *app1 = dynamic_cast<LinkApp *>(a);
789    LinkApp *app2 = dynamic_cast<LinkApp *>(b);
802    LinkApp *app1 = dynamic_cast<LinkApp *>(a.get());
803    LinkApp *app2 = dynamic_cast<LinkApp *>(b.get());
790804    bool app1_is_opk = app1 && app1->isOpk(),
791805         app2_is_opk = app2 && app2->isOpk();
792806
793    if (app1_is_opk && !app2_is_opk)
794            return false;
795    if (app2_is_opk && !app1_is_opk)
796            return true;
807    if (app1_is_opk && !app2_is_opk) {
808        return false;
809    }
810    if (app2_is_opk && !app1_is_opk) {
811        return true;
812    }
797813    return a->getTitle().compare(b->getTitle()) < 0;
798814}
799815
...... 
825841}
826842
827843void Menu::readLinksOfSection(
828        vector<Link*>& links, string const& path, bool deletable)
844        vector<unique_ptr<Link>>& links, string const& path, bool deletable)
829845{
830846    DIR *dirp = opendir(path.c_str());
831847    if (!dirp) return;
...... 
839855            link->setSize(
840856                    gmenu2x.skinConfInt["linkWidth"],
841857                    gmenu2x.skinConfInt["linkHeight"]);
842            links.push_back(link);
858            links.emplace_back(link);
843859        } else {
844860            delete link;
845861        }
src/menu.h
6060    int iSection, iLink;
6161    uint iFirstDispRow;
6262    std::vector<std::string> sections;
63    std::vector<std::vector<Link*>> links;
63    std::vector<std::vector<std::unique_ptr<Link>>> links;
6464
6565    uint linkColumns, linkRows;
6666
...... 
7272     */
7373    void calcSectionRange(int &leftSection, int &rightSection);
7474
75    std::vector<Link*> *sectionLinks(int i = -1);
75    std::vector<std::unique_ptr<Link>> *sectionLinks(int i = -1);
7676
7777    void readLinks();
7878    void freeLinks();
...... 
8989#endif
9090
9191    // Load all the links on the given section directory.
92    void readLinksOfSection(std::vector<Link*>& links,
92    void readLinksOfSection(std::vector<std::unique_ptr<Link>>& links,
9393                            std::string const& path, bool deletable);
9494
9595    /**

Archive Download the corresponding diff file



interactive