首页 > 解决方案 > C++ Android内存泄漏中的撤消/重做

问题描述

我正在 Android 上开发一个手指绘画应用程序。我用 C++ 和卷页一起实现了这个手指画。手指画效果很好,但我想知道我的 undoPen 和 redoPen 方法是否存在内存泄漏。它必须使用原始指针来完成。我只添加了代码的有用部分。

vector<vector<*mPath>>MAIN(12);
vector<*mPath> undoMain(0);
int PageNo = 0;
void Pen::onFingerDown(float x1, float y1)
{
    undoMain.clear();

    MAIN[PageNo].push_back(move(path));
    mx = x1;
    my = y1;
    tempPoints.x1=x1;
    tempPoints.y1=y1;
    tempPoints.x2=x1;
    tempPoints.y2=y1;
    // points.push_back(tempPoints);
    path->addVert(tempPoints);
}

void Pen::onFingerMove(float x, float y)
{
    tempPoints.x1=mx;
    tempPoints.y1=my;
    tempPoints.x2=x;
    tempPoints.y2=y;
    path->addVert(tempPoints);

    // path->addColor(tempColors);
    // points.push_back(tempPoints);

    mx=x;
    my=y;
    //LOG_INFO("LOOOOOL");
}

void Pen::onFingerUp()
{
    path = new mPath();
}

void Pen::undoPen()
{
    if (MAIN[PageNo].size()>0) {
        undoMain.push_back(move(*MAIN[PageNo].erase(MAIN[PageNo].end()-1)));
    }

}

void Pen::redoPen()
{
    if (undoMain.size()>0) {
        MAIN[PageNo].push_back(move(*undoMain.erase(undoMain.end()-1)));

        ////
    }
}

标签: androidc++memory-leaks

解决方案


我没有仔细阅读您的代码,但是当然,每当您在没有相应的隐式或显式删除的情况下调用 new 时都会发生内存泄漏,让我们为此目的使用智能指针。此外:

 vector<vector<PathType>>MAIN(12); // *mPath should be a type, what is the type of mPath 
 vector<PathType> undoMain(0);

我会这样做

 vector<vector<std::unique_ptr<PathType>>>MAIN(12); // 
 vector<std::unique_ptr<PathType>> undoMain(0);

或者如果 MAIN 和 undo undoMAIN 共享相同的数据

vector<vector<std::shared_ptr<PathType>>>MAIN(12); // 
vector<std::shared_ptr<PathType>> undoMain(0);

实际上路径未在您的示例代码中定义

编辑:

我一直在修改我的答案。

首先,也许您应该继续学习和深入研究 C++,忘记托管代码,您的版本令人困惑。事实上我们不会使用智能指针,一切都可以复制而没有太多副作用:

我给你一个修改后的版本:

    typedef vector < fingerPos >            path_type;          // So you low level representation of a path

// Those two must have finite limits ( no more than a given configuration dependant number )
std::deque < path_type >            undo_History  ( 12 );   // no need to reserve anything here ( although you can ), user input are slow.
std::deque < path_type >            redo_History   ( 12 )

struct Path 
{
    path_type                       mlineHolder;

    Path() 
    { } 

    void addVert ( fingerPos vert ) 
    { 
        mlineHolder.push_back(vert); 
    }  

    vector < fingerPos > Path::getPath ( ) 
    { 
        return ( mlineHolder ); 
    }

    ~Path() 
    { 
        // no need it's automatic 
        // mlineHolder.clear();

        // copy the current path to the Undo buffer
        undo_History.push_back ( mlineHolder );     
    } 
};

void Pen::onFingerDown(float x1, float y1)
{
    // Don't undo when user begins a new drawing or you loose your buffers
    // undoMain.clear ( );

    // But clear the redo history since you cannot redo from something different
    redo_History.clear ( );

    mx = x1;
    my = y1;

    tempPoints.x1=x1;
    tempPoints.y1=y1;
    tempPoints.x2=x1;
    tempPoints.y2=y1;

    // points.push_back(tempPoints);
    m_path->addVert ( tempPoints );
}

void Pen::onFingerMove(float x, float y)
{
    tempPoints.x1=mx;
    tempPoints.y1=my;
    tempPoints.x2=x;
    tempPoints.y2=y;

    m_path->addVert(tempPoints);

    // path->addColor(tempColors);
    // points.push_back(tempPoints);

    mx=x;
    my=y;
    //LOG_INFO("LOOOOOL");
}

void Pen::onFingerUp ( )
{
    UndoHistory.push_front ( std::move ( m_path ) );
    // Also add this path to the global structure holding every primitives on screen

}


// Undo should not be part of pen but the top level drawing manager.
void Manager::undo ( )
{
    if ( UndoHistory.size  ( )  ) {
        redo_History. push_front ( undoMain.back ( );
    }

    // then redraw everything form the begining of undo history
    // You must have something holding every primitives on screen that is deeper than redo history
    ...
}

void Pen::redoPen ( )
{
    if  ( redo_History .size ( ) > 0 ) {
        Undo_History. push_front ( RedoMain.back ( );
        // Also add this path to the global structure holding every primitives on screen
    }

    // then redraw everything form the begining then everything from begin to end of undo history
}

确实,向任何事物添加撤消历史记录并不是那么容易。您必须深入了解您的图形引擎。

希望这能有所帮助。


推荐阅读