【问题标题】:How to lessen memory usage - possible memory leakage如何减少内存使用 - 可能的内存泄漏
【发布时间】:2011-03-30 22:50:36
【问题描述】:

我目前正在编写用于图像处理的小型应用程序。但是,我的程序的内存使用存在很大问题。我是 C++ 的新手,以前我主要是用 C# 编程。

几乎完成所有工作的函数看起来像这样

while(!prototypeVector[i]->GetIsConvergaed()) 
{
    if(previousPrototype!=NULL) delete previousPrototype;
    previousPrototype = prototypeVector[i]->CopyPrototype();

    if(&matchingPointVector!=NULL) matchingPointVector.clear();
    matchingPointVector = prototypeVector[i]->CalculateMatchingPointsAll(imageDataVector); 
    distanseMatrix = CalculateDistanceAll(i);

    membershipMatrix = UpdateMembershipAll(i);

    if(translation)
    {
        tmatrix = UpdateTranslationMatrix(i);
        if(directUpdate) prototypeVector[i]->SetTranslationMatrix( tmatrix);

        //prototypeVector[i]->GetTranslationMatrix().DisplayMatrix();
        tmatrix.DisplayMatrix();
    }
    if(scaling)
    {
        smatrix = UpdateScalingMatrix(i);
        if(directUpdate) prototypeVector[i]->SetScalingMatrix(smatrix);
        smatrix.DisplayMatrix();
    }
    if(rotation)
    { 
        angle =  UpdateAngleCoefficient(i);
        cout<<endl;
        Convert::RadiansToDegrees(angle)<<endl;
        if(directUpdate)prototypeVector[i]->UpdateRotationMatrix(angle);
    }

    prototypeVector[i]->TransformTemplateOne(prototypeVector[i]->GetRotationMatrix(), prototypeVector[i]->GetScalingMatrix()  , prototypeVector[i]->GetTranslationMatrix());
}

我注意到如果上面写的函数被称为另一个函数

CalculateMatchingPointsAll 或 CalculateDistanceAll 或 UpdateScalingMatrix 内存使用量急剧上升(执行上述每个函数后为 300kB)。所以我想问题出在这些功能上。他们看起来像那样

vector<Point*> TemplateClusterPoint::CalculateMatchingPointsAll( vector<Point*> imageDataVector)
{
    vector<Point*> matchinPointVector = vector<Point*>(imageDataVector.size(),new Point(0,0));
    double minValue = DOUBLE_MAX_VALUE;
    double currentDistance = 0;
    for (int i=0;i<imageDataVector.size();i++ )
    {
        //matchinPointVector[i] = this->CalculateMatchingPoint(/*prototypePointVector,*/imageDataVector[i]);
        for (int j=0;j<prototypePointVector.size();j++)
        {
            if( (currentDistance = CalculateDistance(imageDataVector[i],prototypePointVector[j]) ) <= minValue )
            {

                minValue = currentDistance;
                matchinPointVector[i] = prototypePointVector[j];
            }
        }
        minValue =   currentDistance = DOUBLE_MAX_VALUE;
    }
    return matchinPointVector;
}


vector<vector<double>> AlgorithmPointBased::CalculateDistanceAll( int clusterIndex)
{
    //vector<Point*> pointVector = prototypeVector[clusterIndex]->GetPrototypePointVector();
    Point* firstPoint = NULL;
    Point* secondPoint = NULL;
    for(int i=0;i<imageDataVector.size();i++ )
    {
        firstPoint = imageDataVector[i];
        secondPoint = matchingPointVector[i];

        distanseMatrix[clusterIndex][i] =  pow( (firstPoint->GetX() - secondPoint->GetX() ), 2    ) + pow( (firstPoint->GetY() - secondPoint->GetY() ), 2);   //(difference*difference)[0][0]; //funkcja dystansu = d^2 = (Xi - Pji)^2
                                                                                    // gdzie Xi punkt z obrazu, Pij matching point w danym klastrze
    }
    return distanseMatrix;
}

Matrix<double> AlgorithmPointBased::UpdateScalingMatrix( int clusterIndex )
{

    double currentPower = 0;
    vector<Point*> prototypePointVecotr = prototypeVector[clusterIndex]->GetPrototypePointVector();
    vector<Point*> templatePointVector = templateCluster->GetTemplatePointVector();
    Point outcomePoint;
    Matrix<double> numerator =  Matrix<double>(1,1,0);
    double denominator=0;
    for (int i=0;i< imageDataVector.size();i++)
    {
        Point templatePoint =  *matchingPointVector[i]; 
         currentPower = pow(membershipMatrix[clusterIndex][i],m);
        numerator += /  ((*imageDataVector[i] - prototypeVector[clusterIndex]->GetTranslationMatrix()).Transpose()* (prototypeVector[clusterIndex]->GetRotationMatrix() * templatePoint )* currentPower);
        denominator += (currentPower* (pow(templatePoint.GetX(),2) +  pow(templatePoint.GetY(),2)));   
    }
     numerator /= denominator;
    return numerator;
}

正如您所见,这些函数所做的几乎所有工作都是计算新点或最近点或转换图像。在执行这些功能后,有什么方法可以以某种方式释放至少一些内存。 我想最消耗内存的操作是矩阵的乘法或点上的操作。我重载了 operator + * 和 / 当然返回新对象。

已编辑 重载的操作符是这样的

Point Point::operator*( double varValue )
{
    return *(new Point(this->x * varValue,this->y * varValue));
}

Point Point::operator-( Point& secondPoint )
{
    return *(new Point(this->x - secondPoint.GetX(),this->y - secondPoint.GetY()));
}

Point Point::operator*( double varValue )
{
    return *(new Point(this->x * varValue,this->y * varValue));
}

template<typename T>
Matrix<T> Matrix<T>::operator + (double value)
{
    Matrix<T>* addedMatrix = new Matrix<T>(this->rows,this->columns);
    for (int i=0;i<this->rows;i++)
    {
        for (int j=0;j<this->columns;j++)
        {
            (*addedMatrix)[i][j] = (*this)[i][j]+ value;
        }
    }
    return *addedMatrix;
}

Point Point::operator/( double varValue )
{
    return *(new Point(this->x / varValue,this->y / varValue));
}

【问题讨论】:

  • "我重载了运算符 + * 和 /,它们当然会返回新对象。"这些功能是什么样的?
  • 如果您正在学习 C++,请确保您拥有 a good introductory book。 C# 和 C++ 是非常不同的语言。
  • @James McNellis 看看我的编辑

标签: c++ optimization memory memory-management


【解决方案1】:

我是 C++ 的新手,以前我主要是用 C# 编程。

与 C# 不同,C++ 没有垃圾收集。任何时候您使用new(例如new Point(0,0)),您都有责任使用delete 销毁该对象。

理想情况下,您应该避免显式动态分配对象并完全避开newdelete。您应该更喜欢创建具有自动存储持续时间的对象(在堆栈上)并使用它们的副本(通过值或引用传递它们,按值返回它们,并将它们的副本存储在容器中)。

除其他外,您几乎可以肯定使用std::vector&lt;Point&gt; 而不是std::vector&lt;Point*&gt;


return *(new Point(this->x * varValue,this->y * varValue)); 

您的所有具有此类代码的函数都是错误的:您动态分配一个对象,返回该对象的副本,并丢失对原始对象的所有引用。您将无法销毁动态分配的对象。您不需要在这里动态分配任何东西。以下内容就足够了:

return Point(x * varValue, y * varValue);

if(&matchingPointVector!=NULL)

这在正确的程序中永远不会是错误的:&amp; 获取对象的地址,并且没有对象可以拥有地址 NULL。发生这种情况的唯一方法是,如果您已经在程序中的某个位置取消引用了一个空指针,在这种情况下,您已经陷入了一大堆麻烦之中。


确保您拥有a good introductory C++ book。 C++ 和 C# 是非常不同的编程语言。

【讨论】:

  • 呃,你不是说通过引用传递对象吗?
  • 说到内存管理,我还要提一下smart pointers
  • 感谢您的回答,不过我还有几个问题。您写道,您写道:“理想情况下,您应该避免显式动态分配对象并完全避免 new 和 delete”,那么 c++ 中现有指针的意义何在。使用它们有什么好处??
【解决方案2】:

C++ 是一种非托管语言,这意味着您必须自己管理内存(正如 James 所说)。当您创建像这样的变量时,例如:int i = 3; 该变量是在系统堆栈上创建的,并且只存在直到它超出范围(花括号 "}" 的末尾),这意味着您不必管理内存为他们。但是,如果您创建一个像 int *ia_array = new int [5]; 这样的变量,您已经创建了一个指针(指向它可以指向任何相同类型的东西,并且可以改变它所指向的东西,这也不会超出范围)然后创建数组在指针指向的堆上。因此,您必须从堆中删除它自己的数组以及指向它的指针。 id 推荐阅读这篇关于动态内存的Cplusplus.com 教程。还可以看看这个非常好的youtubevideo,了解如何正确管理动态分配的内存。最后,如果您最终使用大量指针,您可能需要查找“智能指针”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多