简体   繁体   English

CString的动态3维数组中的内存泄漏

[英]Memory Leak in Dynamic 3 dimensional array of CString

I am working with a dynamic declaration of a 3 dimensional array of type CString. 我正在使用类型为CString的3维数组的动态声明。 (I know, why CString again? Use vectors! I can't, the assignment requires use of cstring.) (我知道,为什么再次使用CString?使用向量!我不能,该赋值需要使用cstring。)

So the assignment is to make a user defined playlist of songs which allows adding, removing, displaying, and searching. 因此,任务是制作一个用户定义的歌曲播放列表,该列表允许添加,删除,显示和搜索。 Also, the playlist must save to a text file called songs.txt. 另外,播放列表必须保存到名为songs.txt的文本文件中。

My problem is I keep getting memory leaks in my adding function I will share all code and memory leak errors, so you can see. 我的问题是我的添加函数中不断出现内存泄漏,我将共享所有代码和内存泄漏错误,因此您可以看到。

Valgrind Errors: Valgrind错误:

==17401== HEAP SUMMARY:
==17401==     in use at exit: 73,519 bytes in 31 blocks
==17401==   total heap usage: 36 allocs, 5 frees, 91,199 bytes allocated
==17401==
==17401== 1 bytes in 1 blocks are definitely lost in loss record 1 of 12
==17401==    at 0x4C284B7: operator new[](unsigned long) (in 
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==17401==    by 0x401BB3: songlist::readList(std::basic_ifstream<char, 
std::char_traits<char> >&)

The rest just kind of repeats itself through 12 of 12 其余的只是在12中的12中重复一次

My code: 我的代码:

defs.cpp: defs.cpp:

#includes <iostream>
#include <cstring>
#include <iomanip>
#include <fstream>
#include "proj4.h"

using namespace std;

void songlist::makeList()
{
        MAX_TRAX = 0;
        song = new char**[20];
        for (int i=0; i<20; i++)
        {
                song[i] = new char*[5];
        }
}

void songlist::readList(ifstream& infile)
{
        int counter = 0;
        if (!infile.is_open())
        {
                cout << "Cannot open file: songs.txt";
        }

        while(!infile.eof())
        {
                infile >> newSong.title >> newSong.artist >> 
newSong.durationMin >> newSong.durationSec >> newSong.album;

                int i = strlen(newSong.title);
                i++;
                int j = strlen(newSong.artist);
                j++;
                int k = strlen(newSong.durationMin);
                k++;
                int l = strlen(newSong.durationSec);
                l++;
                int m = strlen(newSong.album);
                m++;

                if(i>0)
                {

                    song[counter][0]= new char[i];
                    song[counter][1]= new char[j];
                    song[counter][2]= new char[k];
                    song[counter][3]= new char[l];
                    song[counter][4]= new char[m];

                    song[counter][0] = newSong.title;
                    song[counter][1] = newSong.artist;
                    song[counter][2] = newSong.durationMin;
                    song[counter][3] = newSong.durationSec;
                    song[counter][4] = newSong.album;
                    counter++;
            }
            MAX_TRAX = counter-1;
    }

    counter = 0;

}

void songlist::saveList(ofstream& outfile)
{
    if (!outfile.is_open())
    {
            cout << "Cannot find file: songs.txt";
    }

    for (int i=0; i<=MAX_TRAX; i++)
    {
            outfile << song[i][0] << "; " << song[i][1] << "; " << song[i]
[2] << "; " <<song[i][3] << "; " << song[i][4] << ";" << endl;
       }
 }

void songlist::displayList()const
{
    cout << left << setw(16) << '#' << left << setw(30) << "Song Name" << 
   left << setw(22) << "Artist Name" << left << setw(17) << "Duration" << 
left << setw(20) << "Album Title" << endl;
    cout << left << setw(110) << setfill ('-') << '-' << endl;
    cout << setfill (' ');

    if (strlen(newSong.title)>=1)
    {
            for (int i=0; i<=MAX_TRAX; i++)
            {
                    cout << left << setw(4) << i+1 << left << setw(31) << 
song[i][0] << left << setw(31) << song[i][1] << right << setw(4) << song[i]
[2] 
<< ':';
if (strlen(song[i][3])==1)
                            {
                                    cout << '0';
                                    cout << left << setw(3) << song[i][3] << 
left << setw(3) << song[i][4] << endl;
                            }
                    else
                            cout << left << setw(4) << song[i][3] << left << 
setw(3) << song[i][4] << endl;
            }
            cout << left << setw(110) << setfill ('-') << '-' << endl;
            cout << setfill (' ');
    }
}

void songlist::addSong()
{
    if(strlen(newSong.title)>=1)
            {
            MAX_TRAX++;
            }

    cout << "Add a Song" << endl;
    cout << endl;

    cout << "Enter Song Title: ";
    cin.ignore();
    cin.get(newSong.title, 30);
    cout << endl;

    cout << "Enter Artist Name: ";
    cin.ignore();
    cin.get(newSong.artist, 30);
    cout << endl;

    cout << "Enter Track Duration";
    cout << endl;
    cout << "Minutes: ";
    cin.ignore();
    cin.get(newSong.durationMin, 3);
    cout << endl;


    cout << "Seconds: ";
    cin.ignore();
    cin.get(newSong.durationSec, 3);
    cout << endl;

    cout << "Enter Album Title: ";
    cin.ignore();
    cin.get(newSong.album, 30);
    cout << endl;
    cout << "Song Added to Database!";
    cout << endl;
    cout << endl;

            int i = strlen(newSong.title);
            i++;
            int j = strlen(newSong.artist);
            j++;
            int k = strlen(newSong.durationMin);
            k++;
            int l = strlen(newSong.durationSec);
            l++;
            int m = strlen(newSong.album);
            m++;

            song[MAX_TRAX][0]= new char[i];
            song[MAX_TRAX][1]= new char[j];
            song[MAX_TRAX][2]= new char[k];
            song[MAX_TRAX][3]= new char[l];
            song[MAX_TRAX][4]= new char[m];

            song[MAX_TRAX][0] = newSong.title;
            song[MAX_TRAX][1] = newSong.artist;
            song[MAX_TRAX][2] = newSong.durationMin;
            song[MAX_TRAX][3] = newSong.durationSec;
            song[MAX_TRAX][4] = newSong.album;

}
void songlist::removeSong()
{
    int p = 0;
    int q = 0;
    int n = 0;
    cout << "Remove a Song" << endl;
    cout << "Enter Track Number to Confirm Deletion: ";
    cin >> n;
 cout << endl;

    while (!(n >=1 && n <= MAX_TRAX+1))
    {
            cin.clear();
            cin.ignore();
            cout << "Must be a number between 1 and " << MAX_TRAX+1 << endl;
            cout << "Enter Track Number to Confirm Deletion: ";
            cin >> n;
            cout << endl;
    }
    n--;
    for (p=n;p<MAX_TRAX; p++)
    {
            for(q=0;q<5;q++)
            {
                    delete[] song[p][q];
            }

            int i = strlen(song[p+1][0]);
            i++;
            int j = strlen(song[p+1][1]);
            j++;
            int k = strlen(song[p+1][2]);
            k++;
            int l = strlen(song[p+1][3]);
            l++;
            int m = strlen(song[p+1][4]);
            m++;

            song[p][0] = new char[i];
            song[p][1] = new char[j];
            song[p][2] = new char[k];
            song[p][3] = new char[l];
            song[p][4] = new char[m];

            song[p][0] = song[p+1][0];
            song[p][1] = song[p+1][0];
            song[p][2] = song[p+1][0];
            song[p][3] = song[p+1][0];
            song[p][4] = song[p+1][0];
    }

    MAX_TRAX--;
n++;
    cout << "Track Number " << n << " Deleted" << endl;
}

void songlist::searchList()const
{
    int i;
    char aOrB;
    int counter = 0;
    char art[30];
    char alb[30];

    cout << "Search by (a)rtist or al(b)um? (a or b): ";
    cin >> aOrB;
    cout << endl;

    if (aOrB != 'a' && aOrB != 'b')
    {
            cout << "(a or b): ";
            cin >> aOrB;
            cout << endl;
    }

    if (aOrB == 'a')
    {
            cout << "Artist Name: ";
            cin.ignore();
            cin.get(art, 30);

            for(i=0; i<=(MAX_TRAX); i++)
            {
                    if (strcmp(art, song[i][1])==0)
                    {
                            cout << left << setw(2) << i+1 << left << 
setw(32) << song[i][0] << left << setw(32) << song[i][1] << right << setw(4) 
<< song[i][2] << ':' << left << setw(5) << song[i][3] << left << setw(32) << 
song[i][4] << endl;
                            counter++;
                    }
            }
    }

    else
    {
            cout << "Album Name: ";
            cin.ignore();
            cin.get(alb, 30);

            for(i=0; i<=(MAX_TRAX); i++)
            {
                    if (strcmp(alb, song[i][4])==0)
                    {
                            cout << left << setw(2) << i+1 << left << 
setw(32) << song[i][0] << left << setw(32) << song[i][1] << right << setw(4) 
<< 
song[i][2] << ':' << left << setw(5) << song[i][3] << left << setw(32) << 
song[i][4] << endl;
                            counter++;
                    }
            }
    }

    if (!counter)
    {
            cout << endl;
            cout << "No Matches Found; check spelling and/or case." << endl;
    }
}

void songlist::deleteAll()
    {
    for(int i=0; i>=20; i++)
            {
            for (int j=0; j<5; j++)
                    delete[] song[i][j];
            delete[] song[i];
            }
    delete[] song;
    }

songlist::songlist()
{
}

Proj4.h: Proj4.h:

#ifndef PROJ3_H
#define PROJ3_H
#include <iostream>
#include <fstream>
#include <cstring>
#include <iomanip>

using namespace std;

class songlist
{
public:
    void readList(ifstream& infile);
    void saveList(ofstream& outfile);
    void displayList() const;
    void makeList();
    void addSong();
    void removeSong();
    void searchList() const;
    void deleteAll();
    songlist();
private:
    struct songs
            {
            char title[30] = {'\0'};
            char artist[30] = {'\0'};
            int intMin = 0;
            int intSec = 0;
            char durationMin[3] = {'\0'};
            char durationSec[3] = {'\0'};
            char album[30] = {'\0'};
            };
    songs newSong;

    int MAX_TRAX;

    char *** song;
};
#endif

app.cpp: app.cpp:

#include <iostream>
#include <cstring>
#include <iomanip>
#include <fstream>
#include "proj4.h"

using namespace std;

int main()
{
        char selection;

        cout << endl;
        cout << "*Music Track Database*" << endl;

        ifstream infile;
        ofstream outfile;
        infile.open("songs.txt");
        outfile.open("songs.txt");
        songlist newlist;
        newlist.makeList();

        do
        {
                cout << endl;
                cout << "Main Menu:" << endl;
                cout << endl;
                cout << "(a)dd a song" << endl;
                cout << "(r)emove a song" << endl;
                cout << "(d)isplay track listings" << endl;
                cout << "(s)earch for a track" << endl;
                cout << "(q)uit" << endl;
                cout << endl;
                cout << "Select (a, r, d, s, q): ";
                cin >> selection;
                cout << endl;

                if (selection != 'a' && selection != 'r' && selection != 'd' 
&& selection != 's' && selection != 'q')
                {
                        cout <<  "Select (a, r, d, s, q): ";
                        cin >> selection;
                        cout << endl;
                }

switch (selection)
                {
                        case 'a':
                                newlist.readList(infile);
                                newlist.addSong();
                                newlist.saveList(outfile);
                                break;
                        case 'd':
                                newlist.readList(infile);
                                newlist.displayList();
                                break;
                        case 'r':
                                newlist.removeSong();
                                newlist.saveList(outfile);
                                break;
                        case 's':
                                newlist.readList(infile);
                                newlist.searchList();
                                break;
                }
        }while (selection != 'q');

        newlist.deleteAll();

        cout << "Happy Trails To You; Until We Meet Again!" << endl;
        cout << endl;

        infile.close();
        outfile.close();

        return 0;
}

Also here is a simple makefile to test it: 这也是一个简单的makefile来对其进行测试:

all:
        g++ app.cpp proj4.h defs.cpp -o proj4;
clean:
        clean make;

Anything helps! 有什么帮助! Thank You in advance. 先感谢您。

You're not even allowed to use structs or classes? 您甚至不被允许使用结构或类? When you become a three star programmer it's usually very bad. 当您成为三星级程序员时,这通常很糟糕。

Your allocations are off by one (null termination...) 您的分配被减一(空终止...)

But the actual leak is here. 但是实际的泄漏在这里。 Just think what this does: 只需考虑一下这样做:

song[p][0] = new char[i];
song[p][1] = new char[j];
song[p][2] = new char[k];
song[p][3] = new char[l];
song[p][4] = new char[m];

song[p][0] = song[p+1][0];
song[p][1] = song[p+1][0];
song[p][2] = song[p+1][0];
song[p][3] = song[p+1][0];
song[p][4] = song[p+1][0];

You first allocate memory and then throw the pointers away by assigning something else to those pointers. 您首先分配内存,然后通过为这些指针分配其他内容来丢弃这些指针。 You can never get them back and that's a leak. 您永远无法将它们找回来,那是一个漏洞。

Instead of this: 代替这个:

        song[counter][0] = new char[i];
        song[counter][1] = new char[j];
        song[counter][2] = new char[k];
        song[counter][3] = new char[l];
        song[counter][4] = new char[m];

        song[counter][0] = newSong.title;
        song[counter][1] = newSong.artist;
        song[counter][2] = newSong.durationMin;
        song[counter][3] = newSong.durationSec;
        song[counter][4] = newSong.album;

Maybe Something more like: 也许更像是:

        song[counter][0] = new char[i];
        song[counter][1] = new char[j];
        song[counter][2] = new char[k];
        song[counter][3] = new char[l];
        song[counter][4] = new char[m];

        strncpy(song[counter][0], newSong.title, i);
        strncpy(song[counter][0], newSong.artist, j);
        strncpy(song[counter][0], newSong.durationMin, k);
        strncpy(song[counter][0], newSong.durationSec, l);
        strncpy(song[counter][0], newSong.album, m);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM