Как предотвратить утечку памяти, когда нам «приходится» передавать указатели в цикле на какую-то функцию? - PullRequest
0 голосов
/ 04 апреля 2019

У меня возникла ситуация, когда я должен вызывать функцию в цикле с указателем (на объект класса) в качестве параметра.Проблема в том, что я не могу изменить сигнатуру этой функции, и что при каждой итерации цикла я должен инициализировать указатель.Это приведет к утечке памяти, так как я не могу удалить указатель (после передачи его функции) внутри цикла.Можно ли как-то предотвратить утечку памяти в таком случае?

Я хотел бы объяснить на простом примере:

class testDelete
{
    public:
        void setValue(int* val) {vec.push_back(val);};
        void getValue();
    private:
        vector <int*> vec;
};
void testDelete::getValue()
{
    for (int i=0;i<vec.size();i++)
    {
        cout << "vec[" << i << "] = " << *vec[i]<<"\n";
    }
}

int main()
{
    testDelete tD;
    int* value = NULL;
    for (int i=0;i<10;i++)
    {
        value=new int(i+1);
/*I am not allowed to change this function's signature, and hence I am forced to pass pointer to it*/
        tD.setValue(value); 
/*I cannot do delete here otherwise the getValue function will show garbage value*/ 
        //delete value;
    }

    tD.getValue();
    return 0;
}

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Храните целые числа в контейнере:

int main()
{
    std::vector<int> values(10);

    testDelete tD;
    for (int i=0;i<10;i++)
    {
        values[i] = i + 1;
        tD.setValue(&values[i]);
    }

    tD.getValue();
    return 0;
}
2 голосов
/ 04 апреля 2019

Если deleteTest хочет использовать указатели, возможно, пропавших объектов, оно должно содержать std::weak_ptr с. Держать необработанный указатель и разыменовывать его позже опасно (если только вы не можете убедиться, что объект еще жив, a.k.a не используйте необработанные, но умные указатели).

[...] Я не могу изменить сигнатуру этой функции и каждой функции Итерации цикла, я должен инициализировать указатель. Есть ли способ предотвратить утечку памяти в таком случае?

Если вам нужны динамически размещаемые объекты, используйте умные указатели (например, std::smart_ptr для совместного владения). Если вам не нужно их динамически распределять, не делайте этого.

Для примера давайте предположим, что вы не можете изменить deleteTest, тогда для целых чисел нет причин динамически выделять что-либо

int main()
{
    std::array<int,10> x;
    testDelete tD;        
    for (int i=0;i<10;i++)
    {
        x[i] = i+1;
        tD.setValue(&x[i]); 
    }    
    tD.getValue();
    return 0;
}

Возьмите этот код с крошкой соли, на самом деле это deleteTest, который нужно исправить, чтобы избежать проблем.

TL; DR

В вашем примере у вас на самом деле две проблемы. deleteTest может попытаться получить доступ к уже пропущенным объектам и утечкам памяти в main. Использование умных указателей решает оба вопроса.

...