Не склонен ли следующий код к утечке памяти? - PullRequest
5 голосов
/ 06 ноября 2011

Я новичок в C ++, и я хочу знать, склонен ли следующий код к утечке памяти. Здесь я использую указатель std::ostream для перенаправления вывода на консоль или в файл. Для этого я звоню новому оператору на std::ofstream.

#include <iostream>
#include <fstream>

int main() {
    bool bDump;

    std::cout << "bDump bool" << std::endl;
    std::cin >> bDump;

    std::ostream *osPtr;

    if (bDump) {
        osPtr = new std::ofstream("dump.txt");
    } else {
        osPtr = &std::cout;
    }

    *osPtr << "hello";
    return 0;
}

И еще одна вещь, я не закрыл файл, который я открыл при вызове конструктора для ofstream. Есть ли у нас потенциальная ситуация с потерей данных здесь? так как файл не закрыт.

Ответы [ 4 ]

7 голосов
/ 06 ноября 2011

Да.Определенно.Каждый раз, когда вы звоните new без delete, возникает утечка памяти.

После выполнения кода вам необходимо добавить следующее:

        if(bDump)
        {
            delete osPtr;
        }
5 голосов
/ 06 ноября 2011

Как @Mahmoud Al-Qudsi упомянул все, что вы новенькое, также должно быть удалено, иначе это будет утечка.

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

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

#include <iostream>
#include <fstream>

int doStuff()
{
    try
    {
        bool bDump;

        std::cout<<"bDump bool"<<std::endl;
        std::cin>>bDump;

        // Smart pointer to store any dynamic object.
        std::auto_ptr<std::ofstream>   osPtr;

        if(bDump)
        {
            // If needed create a file stream
            osPtr.reset(new std::ofstream("dump.txt"));
        } 

        // Create a reference to the correct stream.
        std::ostream&  log = bDump ? *osPtr : std::cout;

        log << "hello";
     }
     catch(...) {throw;}

 } // Smart pointer will correctly delete the fstream if it exists.
   // This makes sure the destructor is called.
   // This is guaranteed even if exceptions are used. 
2 голосов
/ 06 ноября 2011

Да, все, что new ed, но никогда delete ed, не просачивается.

В некоторых случаях вполне разумно выделить слева направо и по центру, а затем просто выйти, особенно для недолговечных программ пакетного стиля, но, как правило, вы должны delete все, что вы new и delete[] все, что вы new[].

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

0 голосов
/ 06 ноября 2011

В показанном коде нет утечки. Во время выполнения все выделенные объекты являются ссылочными. Утечка памяти происходит только в том случае, если объект был выделен и на него нельзя ссылаться каким-либо образом.

Если указатель выходит из области видимости или его значение изменяется без освобождения объекта, это является утечкой памяти. Но пока указатель находится в самой внешней области видимости и ничто другое не меняет его значение, утечки нет.

"В объектно-ориентированном программировании утечка памяти происходит, когда объект хранится в памяти, но не может быть доступен из исполняемого кода." Википедия - «Утечка памяти»

Другие ответы предполагают, что любая программа, которая использует типовые одноэлементные шаблоны или не освобождает все выделенные объекты до завершения, имеет утечку памяти. Это, ИМО, довольно глупо. В любом случае, если вы примете это определение, почти у каждой программы или библиотеки реального мира есть утечка памяти, и утечки памяти, конечно, не все плохи.

В некотором смысле, этот вид кодирования подвержен утечке памяти, потому что легко изменить значение указателя или выпустить его из области видимости. В этом случае есть фактическая утечка. Но, как показано, утечки нет.

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

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