内存堆和泄漏摘要

时间:2019-09-20 00:41:05

标签: c++ memory-leaks valgrind dynamic-memory-allocation

我正在通过矩阵提交学校研讨会,并且收到有关内存泄漏的警告,但是,当我编译它并通过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转换为一个整数之后,我会不断获得相同的堆摘要,但是现在它从字面上说一切都很好,但是因为它,我无法提交它,因为我的输出和提交矩阵脚本的输出都没有比赛。有办法关闭它吗?

------------------------
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 个答案:

答案 0 :(得分:2)

泄漏只是杂耍

完全没有泄漏。正确的东西被释放了,错误在于一件事情被不必要地分配了。

查看分配数组后如何使用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或类似名称的指针。它应该只是傻瓜,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,并确保对其进行了正确的管理。

一个 CTRL + F 之后...

在给定的代码中,我肯定找不到delete中的m_noOfSubjects

我们该如何解决? std::vector<int>应该是处理此类问题的捷径。 vector会为您管理从分配到取消分配的所有资源管理,并同时正确处理复制和分配。

也就是说,我怀疑这项作业应该教给你的是RAII。在这种情况下,您想要做的是向School类添加一个构造函数和一个析构函数(以及一个复制构造函数和一个赋值运算符,因为if you need a destructor, you almost always need special code to handle copying)。不要在一些School免费功能中分配read的资源,这些功能不会对School类的健康造成伤害。 School应该通过在其构造函数或其自己的输入方法中分配存储空间来寻找自己。稍后,析构函数保证School超出范围后,将释放School的所有资源。您所要做的就是确保School超出范围。