Как уменьшить использование памяти - возможная утечка памяти - PullRequest
0 голосов
/ 31 марта 2011

Я сейчас пишу небольшое приложение для обработки изображений. Однако у меня есть большая проблема с использованием памяти моей программы. Я новичок в 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 использование памяти резко возрастает примерно (300 КБ после выполнения каждой из функций, упомянутых выше). Итак, я полагаю, проблема в этих функциях. Они выглядят так

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;
}

Как вы можете видеть почти всю работу, выполняемую этой функцией, это вычисление новых точек или ближайших точек или преобразование изображения. Есть ли способ как-то освободить хоть какую-то память после того, как эти функции были выполнены. Я предполагаю, что наиболее ресурсоемкими операциями являются умножение матриц или операций над точками. У меня перегружен оператор + * и /, который, конечно, возвращает новые объекты.

EDITED Перегруженные операторы выглядят так

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));
}

Ответы [ 2 ]

10 голосов
/ 31 марта 2011

Я новичок в C ++, ранее я в основном программировал на C #.

В отличие от C #, C ++ не имеет сборки мусора. Каждый раз, когда вы используете new (например, new Point(0,0)), вы несете ответственность за использование delete для уничтожения этого объекта.

В идеале, вы должны избегать динамического выделения объектов явно и избегать new и delete в целом. Вы должны предпочесть создавать объекты с автоматической продолжительностью хранения (в стеке) и работать с их копиями (передавая их по значению или по ссылке, возвращая их по значению и сохраняя их копии в контейнерах).

Помимо прочего, вы почти наверняка должны использовать std::vector<Point> вместо std::vector<Point*>.


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

Все ваши функции с таким кодом неверны: вы динамически распределяете объект, возвращаете копию этого объекта и теряете все ссылки на оригинал. Вы не можете уничтожить динамически размещенный объект. Вам не нужно ничего динамически размещать здесь. Следующего будет достаточно:

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

if(&matchingPointVector!=NULL)

В правильной программе это никогда не может быть ложным: & принимает адрес объекта, и ни один объект не может иметь адрес NULL. Единственный способ, которым это может произойти, - это если вы уже разыменовали нулевой указатель где-то в вашей программе, и в этом случае у вас уже куча проблем.


Убедитесь, что у вас есть хорошая вводная книга по C ++ . C ++ и C # очень разные языки программирования.

0 голосов
/ 31 марта 2011

C ++ - это неуправляемый язык, означающий, что вы должны сами управлять памятью (как сказал Джеймс).Когда вы создаете переменную, например, такую: int i = 3; переменная создается в системном стеке и существует только до тех пор, пока не выпадет из области видимости (конец фигурных скобок "}"), то есть вам не нужно управлять памятьюдля них.Однако, если вы создаете переменную, подобную этой int *ia_array = new int [5];, вы создали указатель (на который можно указать на что-либо того же типа и который может изменить то, на что он указывает, который также не выпадает из области видимости), а затем создать массивв куче, на которую указывает указатель.Поэтому вы должны удалить сам массив из кучи и указатель на него.Я рекомендую прочитать это Cplusplus.com руководство по динамической памяти.Также взгляните на это очень хорошее youtubevideo о том, как правильно управлять динамически выделяемой памятью.Наконец, вы можете поискать «умные указатели», если в конечном итоге вы используете много указателей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...