2013-05-01 2 views
0

Я пытаюсь отключить свой C++. Я сбил простую программу, чтобы найти последовательность Фибоначчи с воспоминаниями. Там утечка памяти, и я не могу понять, почему. Утечка сообщается в Fibonacci :: setToFind.Утечка памяти в фрагменте кода

Извините за длинный кусок кода, но я не мог понять, как сделать более минимальный воспроизводимый пример.

#include <iostream> 

class Fibonacci 
{ 
public: 
    int m_valuefound; 
    int m_tofind; 
    long int *m_memo; 

    int findValue(int value){ 
     if (m_memo[value] == 0) { 
      if (value == 0 || value == 1) { 
       m_memo[value] = 1; 
      } else { 
       m_memo[value] = findValue(value-1) + findValue(value-2); 
      } 
     } 
     return m_memo[value]; 
    } 

    void setToFind(int value){ 
     m_tofind = value; 
     m_memo = new long int[value]; 

     std::fill_n(m_memo,value,0); 
    } 

    void solve(){ 

     int value = m_tofind; 
     int result = findValue(value); 

     std::cout<< "Value is: " << result << std::endl; 
    } 

    ~Fibonacci(){}; 


}; 

int main (int argc, char * const argv[]) { 
    std::cout << "Enter integer values until you'd like to quit. Enter 0 to quit:"; 

    int user_ind=0; 

    // for testing non-interactivly 
    while(true){ 
    for (user_ind=1; user_ind<45; user_ind++) { 
     Fibonacci *test = new Fibonacci; 
     test->setToFind(user_ind); 
     test->solve(); 
      delete test; 
    } 

    } 

    return 0; 
} 
+0

Я не вижу 'delete [] m_memo' в любом месте кода. –

+0

protip: Не используйте указатели. Если m_memo был вектором или deque, и вы написали 'Fibonacci test' вместо теста в качестве указателя, у вас никогда не было бы утечки – 2013-05-01 18:58:11

+0

@ShafikYaghmour Nitpicking, но я думаю, что это должно быть' delete [] m_memo'. –

ответ

5

Вы никогда не удалять m_memo в деструктор Fibonacci.

Поскольку вы распределение m_memo как массив, вы должны удалить с delete[] m_memo

+0

Когда я добавляю оператор delete, я возвращаю мусор обратно для значений последовательности во втором прогоне (и остальном) цикла while. – Sevenless

+0

Какие значения последовательности? Вы имеете в виду выходное значение, которое вы получаете в 'solve()' - мусор? – Ryan

+0

Последовательности значений Я только что получил было: Значения: 2 Значения: 2 Значения: 21 Значения: 2 Значения: 2584 Значения: 2 Значения: 2178309 Значения: 2 – Sevenless

1

Вы направляете m_memo в setToFind:

m_memo = new long int[value]; 

но ваш destructor не имеет delete [] m_memo. Вы должны инициализировать m_memo в вашем constructor и сделать вас класс, не копируемым отключив ваш copy constructor и assignment operator с помощью delete при использовании C++ 11:

Fibonacci(const Fibonacci&) = delete; 
const Fibonacci& operator=(const Fibonacci&) = delete; 

В противном случае вы можете сделать их частными. Если вы использовали контейнер, такой как std::vector, ваша жизнь была бы намного проще.

+0

Даже если у него есть деструктор, он все еще не инициализирует указатель, и ему все равно нужно удалить конструктор копирования и оператор присваивания. – pmr

+0

@pmr исправлено ответ –

2

Вот рабочий код с не скопированным классом Fibonacci. Почему не вы выделяете память в конструкторе. Используйте RAII, где возможно, и помните Правило пяти. Избегайте всего этого, в первую очередь, , используя std::vector.

#include <iostream> 

class Fibonacci 
{ 
public: 
    int m_valuefound; 
    int m_tofind; 
    long int *m_memo; 

    int findValue(int value){ 
     if (m_memo[value] == 0) { 
      if (value == 0 || value == 1) { 
       m_memo[value] = 1; 
      } else { 
       m_memo[value] = findValue(value-1) + findValue(value-2); 
      } 
     } 
     return m_memo[value]; 
    } 

    void setToFind(int value){ 
     m_tofind = value; 
     m_memo = new long int[value]; 

     std::fill_n(m_memo,value,0); 
    } 

    void solve(){ 

     int value = m_tofind; 
     int result = findValue(value); 

     std::cout<< "Value is: " << result << std::endl; 
    } 

    // why don't you allocate in the constructor? 
    Fibonacci() : m_valuefound(0), m_tofind(0), m_memo(nullptr) {} 

    ~Fibonacci() { 
    delete[] m_memo; 
    }; 
    // make the class non-copyable 
    Fibonacci(const Fibonacci&) = delete; 
    const Fibonacci& operator=(const Fibonacci&) = delete; 
    /* 
    C++03 non-copyable emulation 
private: 
    Fibonacci(const Fibonacci&); 
    const Fibonacci& operator=(const Fibonacci&); 
    */ 
}; 
+0

'delete [] m_memo' –

+0

@JoachimIsaksson Уже исправлено. Понял это, ударив по почте. – pmr

+0

+1 для устранения всех проблем сразу –

0

Предлагаю вам использовать больше алгоритмов STL. Вот фрагмент кода с довольно не оптимизированным функтором, но вы можете получить представление о силе СТЛА:

#include <vector> 
#include <algorithm> 
#include <iostream> 

using namespace std; 

class Fibonacci 
{ 
public: 
    Fibonacci(); 
    ~Fibonacci() {} 

    int operator()(); 
private: 
    int n0_; 
    int n1_; 
    int n_; 
}; 

Fibonacci::Fibonacci():n0_(0),n1_(1),n_(0) 
{ 
} 

int Fibonacci::operator()() 
{ 
    if(n_ > 1) 
     return (++n0_) + (++n1_); 
    else 
     return ++n_; 
} 

using namespace std; 
int main() 
{ 
    Fibonacci func; 
    vector<int> v; 

    //generate 100 elements 
    generate_n(v.begin(),100,func); 

    //printing the values using a lambda expression 
    for_each(v.begin(),v.end(),[](const int val){cout << val << endl;}); 

    return 0; 
} 

Вы можете применить алгоритм ознакомительных вы хотите на векторе с использованием find_if и определяющим свой собственный функтор.

Смежные вопросы