Память кучи и утечка резюме - PullRequest
1 голос
/ 20 сентября 2019

Я отправляю свой школьный семинар через матрицу и получаю это предупреждение об утечке памяти, однако, когда я компилирую его и запускаю команду g ++ или VS, он не показывает никаких предупреждений или ошибок.

Это начало представления

Checking due date:
ON TIME.

Compiling:
g++ -Wall -std=c++11 -o ws utils.o School.cpp schoolTester.cpp Subject.cpp utils.cpp 2> errors.txt

Compile result:
Success! no errors or warnings...

Testing execution:
READ THE FOLLOWING CAREFULLY!
I am about to execute the tester and capture the output in "student_output.txt"
Please enter the values carefuly and exactly as instructed.
Press <ENTER> to start...
Script started, file is student_output.txt
==203824== Memcheck, a memory error detector
==203824== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==203824== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==203824== Command: ws
==203824==
Begin Testing the Program!
--------------------------

Please enter the name of the school:
>

Когда я запускаю код, я получаю это резюме

------------------------
End Testing the Program!
==209192==
==209192== HEAP SUMMARY:
==209192==     in use at exit: 200 bytes in 1 blocks
==209192==   total heap usage: 9 allocs, 8 frees, 366 bytes allocated
==209192==
==209192== LEAK SUMMARY:
==209192==    definitely lost: 200 bytes in 1 blocks
==209192==    indirectly lost: 0 bytes in 0 blocks
==209192==      possibly lost: 0 bytes in 0 blocks
==209192==    still reachable: 0 bytes in 0 blocks
==209192==         suppressed: 0 bytes in 0 blocks
==209192== Rerun with --leak-check=full to see details of leaked memory
==209192==
==209192== For counts of detected and suppressed errors, rerun with: -v
==209192== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Script done, file is student_output.txt

Вот сам код:

School.cpp

namespace sdds {

    School Sch;
    Subject Sub[5];

    void read(School& Sch) {
        Sch.m_name = new char[30];
        char name [61];
        cout << "Please enter the name of the school:\n> ";
        read( name, 61, "Name is too long, only 60 characters allowed!\nRedo Entry: ");

        strcpy(Sch.m_name, name);
        cout << "Please enter the number of subjects offered by " << Sch.m_name << ": ";
        Sch.m_noOfSubjects = new int[50];
        read(*Sch.m_noOfSubjects, 2, 50, "Invalid Number of subjects, 2<=ENTRY<=50\nRedo Entry: ");
        Sch.m_subjects = new int[*Sch.m_noOfSubjects];

        for (int i = 0; i < *Sch.m_noOfSubjects; i++) {
            cout << i+1 << ") ------------------------------" << endl;
            read(Sub[i]);


        }
    }

    int report(const School&Sch) {
        int totalEnr = 0;

        cout << Sch.m_name<<endl;
        cout << "Subject Enrollments" << endl;

        for (int i = 0; i < *Sch.m_noOfSubjects; i++) {
            totalEnr += report(Sub[i]);



        }
        cout << "Total enrollment: " << totalEnr;
        return totalEnr;
    }

    void freeMem(School& Sch) {

        delete [] Sch.m_name;
        Sch.m_name = NULL;

        for (int i = 0; i < *Sch.m_noOfSubjects; i++) {
            freeMem (Sub[i]);
        }

        delete [] Sch.m_subjects;
        Sch.m_subjects = NULL;
    }

}

Subject.cpp

namespace sdds {






    void read(char* str) {

        cout << "Enter subject name: ";

        read(str, 71, "Name is too long, only 70 characters allowed!\nRedo Entry : ");

    }

    void read(int& noofSections) {

        cout << "Enter number of sections: ";

        read(noofSections, 0, 11, "Invalid Number of sections, 1<=ENTRY<=10\nRedo Entry: ");

    }

    void read(int noOfStdsInSecs[], int noOfSections) {
                cout << "Enter the number of students in each one of the " << noOfSections << " sections:" << endl;


        for (int i = 0; i < noOfSections; i++) {

            cout << i+1 << ": ";
            read(noOfStdsInSecs[i], 5, 35, "Invalid Number of students, 5<=ENTRY<=35\nRedo Entry: ");

        }


    }

    void read(Subject& Sub) {


        char subjectName[71];
        read(subjectName);
        Sub.m_subjectName = new char[50];
        strcpy(Sub.m_subjectName, subjectName);

        Sub.m_noOfSections = new int;
        read(*Sub.m_noOfSections);


        Sub.m_noOfStdsInSecs = new int [*Sub.m_noOfSections];
        read(Sub.m_noOfStdsInSecs, *Sub.m_noOfSections);

    }

void freeMem(Subject& Sub) {

        delete[] Sub.m_subjectName;
        Sub.m_subjectName = NULL;
        delete Sub.m_noOfSections;
        Sub.m_noOfSections = NULL;
        delete [] Sub.m_noOfStdsInSecs;
        Sub.m_noOfStdsInSecs = NULL;

    }

ОБНОВЛЕНО: После превращения объекта Sch.m_noOfSubjects в просто int я продолжаю получать одно и то же резюме кучи, но теперь оно буквально говорит, что все в порядкено из-за этого я не могу отправить его, так как мои выходные данные и выходные данные из сценария матрицы представления не совпадают.Есть ли способ как-то его отключить?

------------------------
End Testing the Program!
==1821==
==1821== HEAP SUMMARY:
==1821==     in use at exit: 0 bytes in 0 blocks
==1821==   total heap usage: 8 allocs, 8 frees, 166 bytes allocated
==1821==
==1821== All heap blocks were freed -- no leaks are possible
==1821==
==1821== For counts of detected and suppressed errors, rerun with: -v
==1821== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Script done, file is student_output.txt

Checking output:
In line number 33 of your output:
The output should be:

^
But your output is:
[38;5;9m------------------------
^

1 Ответ

2 голосов
/ 20 сентября 2019

Утечка - это просто боковое шоу

Не должно быть никакой утечки.Правильные вещи освобождаются, а ошибка заключается в том, что одна вещь выделяется без необходимости.

Посмотрите, как m_noOfSubjects используется после выделения массива:

read(*Sch.m_noOfSubjects, 2, 50, "Invalid Number of subjects, 2<=ENTRY<=50\nRedo Entry: ");

и

Sch.m_subjects = new int[*Sch.m_noOfSubjects];

и

for (int i = 0; i < *Sch.m_noOfSubjects; i++) 

Все используют ровно одно значение: самое первое.Это не поведение массива.Это поведение единственного int.

m_noOfSubjects не должно быть указателем на массив или int или чем-то в этом роде.Это должно быть просто глупо, ol 'int.

В определении School заменить

int * m_noOfSubjects;

на

int m_noOfSubjects;

, затем удалитьвыделение

Sch.m_noOfSubjects = new int[50];

и, наконец, устранение всех разыменований.Например,

read(*Sch.m_noOfSubjects, 2, 50, "Invalid Number of subjects, 2<=ENTRY<=50\nRedo Entry: ");
     ^ remove

и

Sch.m_subjects = new int[*Sch.m_noOfSubjects];
                         ^ remove

и

for (int i = 0; i < *Sch.m_noOfSubjects; i++) 
                    ^ remove

Процесс мышления по отслеживанию и предотвращению утечек памяти (оригинальный ответ)

Отчетговорит, что один блок из 200 байтов потерян.Вы можете посмотреть в своем коде, где вы выделяете 200 байтов, и исследовать более внимательно.Например, если int - 32 бита, Sch.m_noOfSubjects = new int[50]; соответствует счету 32 бита = 4 байта.4 * 50 = 200.

Давайте проследим за m_noOfSubjects и убедимся, что он правильно управляется.

one CTRL + F позже ...

Конечно, я нигде не могу найти delete из m_noOfSubjects в данном коде.

Как мы можем это исправить?std::vector<int> следует использовать для решения такой проблемы.vector присматривает за всеми средствами управления ресурсами от вас до выделения ресурсов и добавляет правильную обработку копирования и назначения одновременно.

Тем не менее, я подозреваю, что это задание должно научить вас RAII .В этом случае вам нужно добавить конструктор и деструктор (а также конструктор копирования и оператор присваивания, потому что если вам нужен деструктор, вам почти всегда нужен специальный код для обработки копирования ) вSchool класс.Не выделяйте ресурсы School в какой-либо бесплатной функции read, которая не заботится о здоровье и благополучии класса School.School должен следить за собой, выделяя хранилище в своем конструкторе или в своем собственном методе ввода.Позже деструктор гарантирует, что все ресурсы School будут освобождены, как только School выйдет из области видимости.Все, что вам нужно сделать, это убедиться, что School выходит из области видимости.

...