Memory is not freed

882
2
08-04-2017 01:13 AM
TakahiroKAMIYA
Esri Contributor

Hello,

Drop it on the map with GraphicsOverlay,
If you delete it with Clear,
I am in trouble that the memory will not be released.

Do you have any problems?

// Copyright 2016 ESRI                                                                                                                                                                                    
//                                                                                                                                                                                    
// All rights reserved under the copyright laws of the United States                                                                                                                                                                                    
// and applicable international laws, treaties, and conventions.                                                                                                                                                                                    
//                                                                                                                                                                                    
// You may freely redistribute and use this sample code, with or                                                                                                                                                                                    
// without modification, provided you include the original copyright                                                                                                                                                                                    
// notice and use restrictions.                                                                                                                                                                                    
//                                                                                                                                                                                    
// See the Sample code usage restrictions document for further information.                                                                                                                                                                                    
//                                                                                                                                                                                    
#include <sys/resource.h>                                                                                                                                                                                    
                                                                                                                                                                                    
#include "ArcGISTiledLayer.h"                                                                                                                                                                                    
#include "Basemap.h"                                                                                                                                                                                    
#include "Map.h"                                                                                                                                                                                    
                                                                                                                                                                                    
#include "PolygonBuilder.h"                                                                                                                                                                                    
#include "PolylineBuilder.h"                                                                                                                                                                                    
#include "SimpleFillSymbol.h"                                                                                                                                                                                    
#include "SimpleLineSymbol.h"                                                                                                                                                                                    
                                                                                                                                                                                    
#include "ArcGIS.h"                                                                                                                                                                                    
                                                                                                                                                                                    
ArcGIS::ArcGIS(QWidget *parent /*=nullptr*/):                                                                                                                                                                                    
    QMainWindow(parent)                                                                                                                                                                                    
{                                                                                                                                                                                    
    SpatialReference sr(30165);                                                                                                                                                                                    
    MapGraphicsView *m_mapView = new MapGraphicsView(this);                                                                                                                                                                                    
                                                                                                                                                                                    
    ArcGISTiledLayer *tiledLayer = new ArcGISTiledLayer(new TileCache("/users/test/gis001/tpk/16000-4000.tpk", this), this);                                                                                                                                                                                    
    tiledLayer->setVisible(true);                                                                                                                                                                                    
    tiledLayer->setOpacity(0.8);                                                                                                                                                                                    
                                                                                                                                                                                    
    Map *m_map = new Map(new Basemap(tiledLayer, this), this);                                                                                                                                                                                    
    m_map->setInitialViewpoint(Viewpoint(Point(110867.18539903179,-106473.50196292577, sr), 10000.0));                                                                                                                                                                                    
    m_mapView->setMap(m_map);                                                                                                                                                                                    
                                                                                                                                                                                    
    GraphicsOverlay *graphicsOverlay = new GraphicsOverlay(this);                                                                                                                                                                                    
    graphicsOverlay->setRenderingMode(GraphicsRenderingMode::Static);                                                                                                                                                                                    
    m_mapView->graphicsOverlays()->append(graphicsOverlay);                                                                                                                                                                                    
                                                                                                                                                                                    
    setCentralWidget(m_mapView);                                                                                                                                                                                    
                                                                                                                                                                                    
    // グラフィック生成前メモリ使用量を表示
    // Display memory usage before graphic generation                                                                                                                                                                                    
    print();                                                                                                                                                                                    
                                                                                                                                                                                    
                                                                                                                                                                                    
    // 10000回グラフィックを生成(三角形+塗り潰し)                                                                                                                                                                                    
    for (int i = 0; i < 10000; ++i) {                                                                                                                                                                                    
        PolygonBuilder polyBUilder(sr);                                                                                                                                                                                    
        polyBUilder.addPoint(Point(110867.18539903179 + i * 10, -106473.50196292577 + i * 10, sr));                                                                                                                                                                                    
        polyBUilder.addPoint(Point(110865.2853990318  + i * 10, -106474.8019629257  + i * 10, sr));                                                                                                                                                                                    
        polyBUilder.addPoint(Point(110865.48539903181 + i * 10, -106475.6019629257  + i * 10, sr));                                                                                                                                                                                    
        polyBUilder.addPoint(Point(110868.8853990318  + i * 10, -106488.10196292578 + i * 10, sr));                                                                                                                                                                                    
                                                                                                                                                                                    
        SimpleFillSymbol *nestingSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor("#FF008000"), this);                                                                                                                                                                                    
        Graphic *g = new Graphic(polyBUilder.toGeometry(), nestingSymbol, this);                                                                                                                                                                                    
        graphicsOverlay->graphics()->append(g);                                                                                                                                                                                    
    }                                                                                                                                                                                    
                                                                                                                                                                                    
    // グラフィック生成後メモリ使用量を表示
    // Display memory usage before graphic generation                                                                                                                                                                                    
    print();                                                                                                                                                                                    
                                                                                                                                                                                    
                                                                                                                                                                                    
#if 0                                                                                                                                                                                    
                                                                                                                                                                                    
    // 削除パターン1  GraphicListModelをclearする                                                                                                                                                                                    
    graphicsOverlay->graphics()->clear();                                                                                                                                                                                    
                                                                                                                                                                                    
    // グラフィック削除後メモリ使用量を表示                                                                                                                                                                                    
    // Display memory usage after graphic deletion
    print();                                                                                                                                                                                    
                                                                                                                                                                                    
    // 結果 -> メモリ使用量変わらず                                                                                                                                                                                    
    // result -> memory usage remains unchanged                                                                                                                                                                               
#elif 0                                                                                                                                                                                    
                                                                                                                                                                                    
    // 削除パターン2  GraphicListModelから1個ずつremoveする                                                                                                                                                                                    
    GraphicListModel *model = graphicsOverlay->graphics();                                                                                                                                                                                    
                                                                                                                                                                                    
    while (model->size() > 0) {                                                                                                                                                                                    
        Graphic *g = model->first();                                                                                                                                                                                    
        model->removeOne(g);                                                                                                                                                                                    
    }                                                                                                                                                                                    
                                                                                                                                                                                    
    // グラフィック削除後メモリ使用量を表示                                                                                                                                                                                    
    // Display memory usage after graphic deletion
    print();                                                                                                                                                                                    
                                                                                                                                                                                    
    // 結果 -> メモリ使用量変わらず                                                                                                                                                                                    
    // result -> memory usage remains unchanged                                                                                                                                                                                    
#elif 0                                                                                                                                                                                    
                                                                                                                                                                                    
    // 削除パターン3  GraphicListModelから1個ずつremoveし、さらにGraphicを自前でdeleteする                                                                                                                                                                                    
    GraphicListModel *model = graphicsOverlay->graphics();                                                                                                                                                                                    
                                                                                                                                                                                    
    while (model->size() > 0) {                                                                                                                                                                                    
        Graphic *g = model->first();                                                                                                                                                                                    
        model->removeOne(g);                                                                                                                                                                                    
        delete g;                                                                                                                                                                                    
    }                                                                                                                                                                                    
                                                                                                                                                                                    
    // グラフィック削除後メモリ使用量を表示                                                                                                                                                                                    
    // Display memory usage after graphic deletion
    print();                                                                                                                                                                                    
                                                                                                                                                                                    
    // 結果 -> メモリ使用量変わらず                                                                                                                                                                                    
    // result -> memory usage remains unchanged                                                                                                                                                                                         
#elif 0                                                                                                                                                                                    
                                                                                                                                                                                    
    // 削除パターン4  GraphicListModelから1個ずつremoveし、さらにGraphicとその中のSymbolを自前でdeleteする                                                                                                                                                                                    
    GraphicListModel *model = graphicsOverlay->graphics();                                                                                                                                                                                    
                                                                                                                                                                                    
    while (model->size() > 0) {                                                                                                                                                                                    
        Graphic *g = model->first();                                                                                                                                                                                    
        Symbol *sls = g->symbol();                                                                                                                                                                                    
        model->removeOne(g);                                                                                                                                                                                    
                                                                                                                                                                                    
        g->setSymbol(NULL);                                                                                                                                                                                    
        delete sls;                                                                                                                                                                                    
                                                                                                                                                                                    
        delete g;                                                                                                                                                                                    
    }                                                                                                                                                                                    
                                                                                                                                                                                    
    // グラフィック削除後メモリ使用量を表示 
    // Display memory usage after graphic deletion                                                                                                                                                                                   
    print();                                                                                                                                                                                    
                                                                                                                                                                                    
    // 結果 -> メモリ使用量変わらず                                                                                                                                                                                    
    // result -> memory usage remains unchanged                                                                                                                                                                                    
#elif 1                                                                                                                                                                                    
                                                                                                                                                                                    
    // 削除パターン5  GraphicListModelから1個ずつremoveし、さらにGraphicとその中のSymbolを自前でdeleteし、                                                                                                                                                                                    
    //              加えてGraphicsOverlayまでも削除する                                                                                                                                                                                    
    GraphicListModel *model = graphicsOverlay->graphics();                                                                                                                                                                                    
                                                                                                                                                                                    
    while (model->size() > 0) {                                                                                                                                                                                    
        Graphic *g = model->first();                                                                                                                                                                                    
        Symbol *sls = g->symbol();                                                                                                                                                                                    
        model->removeOne(g);                                                                                                                                                                                    
                                                                                                                                                                                    
        g->setSymbol(NULL);                                                                                                                                                                                    
        delete sls;                                                                                                                                                                                    
                                                                                                                                                                                    
        delete g;                                                                                                                                                                                    
    }                                                                                                                                                                                    
                                                                                                                                                                                    
    m_mapView->graphicsOverlays()->removeOne(graphicsOverlay);                                                                                                                                                                                    
    delete graphicsOverlay;                                                                                                                                                                                    
                                                                                                                                                                                    
    // グラフィック削除後メモリ使用量を表示
    // Display memory usage after graphic deletion                                                                                                                                                                                    
    print();                                                                                                                                                                                    
                                                                                                                                                                                    
    // 結果 -> メモリ使用量変わらず                                                                                                                                                                                    
    // result -> memory usage remains unchanged                                                                                                                                                                                         
#endif                                                                                                                                                                                    
}                                                                                                                                                                                    
                                                                                                                                                                                    
void ArcGIS::print()                                                                                                                                                                                    
{                                                                                                                                                                                    
    struct rusage psinfo;                                                                                                                                                                                    
                                                                                                                                                                                    
    if (getrusage(RUSAGE_SELF, &psinfo) == 0) {                                                                                                                                                                                    
        fprintf(stderr, "memory usage : %ld kb\n", psinfo.ru_maxrss);                                                                                                                                                                                    
    }                                                                                                                                                                                    
}                                                                                                                                                                                    
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

// Copyright 2016 ESRI                                                                                                         
//                                                                                                         
// All rights reserved under the copyright laws of the United States                                                                                                         
// and applicable international laws, treaties, and conventions.                                                                                                         
//                                                                                                         
// You may freely redistribute and use this sample code, with or                                                                                                         
// without modification, provided you include the original copyright                                                                                                         
// notice and use restrictions.                                                                                                         
//                                                                                                         
// See the Sample code usage restrictions document for further information.                                                                                                         
//                                                                                                         
                                                                                                         
#ifndef ARCGIS_H                                                                                                         
#define ARCGIS_H                                                                                                         
                                                                                                         
#include <QMainWindow>                                                                                                         
#include "MapGraphicsView.h"                                                                                                         
                                                                                                         
using namespace Esri::ArcGISRuntime;                                                                                                         
                                                                                                         
class ArcGIS : public QMainWindow                                                                                                         
{                                                                                                         
    Q_OBJECT                                                                                                         
public:                                                                                                         
    ArcGIS(QWidget *parent = nullptr);                                                                                                         
                                                                                                         
private:                                                                                                         
    void print();                                                                                                         
};                                                                                                         
                                                                                                         
#endif // ARCGIS_H                                                                                                         
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
2 Replies
LukeSmallwood
Esri Contributor

Hi Takahiro KAMIYA‌, thanks for reporting this problem. I am able to reproduce the memory issue that you are seeing and have a logged an issue to investigate further. However, there are a few ways to deal with this in your example code:

- the first is that you do not need to create a new Symbol for every Graphic which you create in the loop. If you create one Symbol it can be passed to the constructor of each Graphic (this should reduce the amount of memory you are allocating)

- secondly, you are providing the "this" object as the parent QObject for both the Symbols and the Graphics which means that they will be preserved until the parent object is deleted (in this case when the app exits). Appending the graphic to the GraphicsListModel does not transfer ownership so it will not be freed when the model is cleared. One way to tackle this is to provide a "local parent" which you can delete whenever you clear the model - e.g. 

   QObject* localParent = new QObject(this); // new local parent object

   ...
   Graphic *g = new Graphic(polyBUilder.toGeometry(), nestingSymbol, localParent); // pass as parent instead of this
   ...
   model->clear(); // when you clear the model also delete the parent to delete all of the child objects
   delete localParent;

I hope that helps,

Luke

TakahiroKAMIYA
Esri Contributor

Hello Luke,

Sorry, the reply was delayed.

Thank you for information.

This method seems to be OK.
Thank you.

Takahiro.

0 Kudos