2013-03-28 5 views
2

Я использую VLD для обнаружения утечек памяти в игре, которую я пишу на C++. До недавнего времени он сообщал об отсутствии утечек. У меня есть класс SettingsManager (все статические методы), который загружает настройки и может сохранять их (файл ввода-вывода). Вот как я бы загрузить список параметров «ключ = значение» в векторе:Почему у меня есть утечки памяти?

std::vector<Setting*> settings; 
SettingsManager::loadFromFile(settingsLocation + "display" + settingsExtension, settings); 

Этот вектор правильно заполнен, и я могу дополнительно обрабатывать данные. Метод LoadFromFile() реализуется следующим образом:

std::ifstream file; 
file.open(filename); 
if(file.is_open()) 
{ 
    std::string line; 
    unsigned pos; 
    while(file.good()) 
    { 
     Setting* s = new Setting; 
     getline(file, line); 
     if(line.empty()) 
     { 
      // do not read empty lines 
      continue; 
     } 
     // parse to Setting 
     pos = line.find('='); 
     s->key = line.substr(0, pos); 
     s->value = line.substr(pos + 1); 
     // add to vector 
     settings.push_back(s); 
    } 
    file.close(); 
    return true; 
} 
else 
{ 
    return false; 
} 

Таким образом, это выделяет Настройки (которая является простой структурой, состоящей из двух станд :: строковых переменных). Я удалить их оттуда, где я называю метод LoadFromFile следующим вызовом метода:

SettingsManager::deleteSettings(settings); 

, который реализуется следующим образом:

void SettingsManager::deleteSettings(std::vector<Setting*>& settings) 
{ 
    for(std::vector<Setting*>::iterator it = settings.begin(); it != settings.end(); ++it) 
    { 
      delete (*it); 
    } 
} 

Когда я отладки, после deleteSettings называют все элементы в векторе являются Bad Ptr (Visual Studio 2010 Express). Если я назначу NULL на *, то после инструкции delete все они будут NULL. Поэтому я действительно не вижу причин, почему это дает мне утечки памяти.

У кого-нибудь есть идея? Благодаря!

+0

использовать 'std :: unique_ptr', и проблема магически исправляет себя или становится ошибкой компилятора, которая помогает вам исправить ее вручную. –

+0

Вероятно, нам нужно увидеть заголовок класса 'Настройки', а также код его деструктора. – jdehaan

+1

Я не знаю ответа, это может быть ложным положительным. Но есть одна легкая вещь, которую вы можете сделать. Не используйте указатели! Если у вас просто есть 'std :: vector ' not 'std :: vector ', то определенно не будет никаких утечек. Я не вижу никакой веской причины использовать указатели для этого. – john

ответ

5

Заявление continue вызывает по меньшей мере одну утечку. Начало цикла выделяет новое значение Setting и продолжает покидать тело цикла, не освобождая память. Вам нужно удалить его, чтобы предотвратить утечку.

Setting* s = new Setting; 
getline(file, line); 
if(line.empty()) { 
    delete s; 
    continue; 
} 

В целом, хотя вы играете с ручным управлением памятью здесь, и легко ошибиться. Я настоятельно рекомендую вам использовать такой тип, как shared_ptr<Setting> вместо необработанного Setting*. Это сделает ваш код гораздо более надежным

+0

Спасибо за быстрый ответ! Является ли shared_ptr чем-то со стандартного C++ или из библиотеки, такой как Boost? – RaptorDotCpp

+0

@RaptorDotCpp Я верю, что 'shared_ptr' возник в boost, но теперь является частью C++ 11 – JaredPar

+0

Хорошо, я обязательно проверю это – RaptorDotCpp

0

будут сдвинуты

Setting* s = new Setting; 

, чтобы после того, как продолжить цикл, который будет исправить вашу проблему.

Редактировать:

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

Поставив код, создающий объект установки после утверждения пустой строки, вы должны исправить эту проблему.

+0

Получает смысл, спасибо! – RaptorDotCpp

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