无法隔离内存泄漏

时间:2015-02-23 00:10:25

标签: c++ memory-leaks

我正在使用Visual Studio泄漏检测工具:https://visualstudiogallery.msdn.microsoft.com/7c40a5d8-dd35-4019-a2af-cb1403f5939c

这给了我泄漏的行号,因为在我的生命中,我不能让#define _CRTDBG_MAP_ALLOC为我提供描述性的输出。如果您在我的代码中看到我错误地使用它,请说出来,我想知道如何正确使用它,但就目前而言,视觉泄漏检测工具运行良好。

我一直在发现2个内存泄漏,一个在project4.cpp第58行,另一个在tasklist.cpp第13行。

当我调用delete myTaskList时,第一个泄漏project4.cpp第58行应该在我的main函数的return语句之前用delete语句密封。

当我调用TaskList类的重写析构函数时,应该密封第二个泄漏taskList.cpp第13行:

//destructor to delete all dynamically allocated memory
TaskList::~TaskList() {
    delete[] arrayOfTasks;
    arrayOfTasks = NULL;
}

我很难过为什么这些泄漏仍然出现。这是我的主要功能:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include "Task.h"
#include "TaskList.h"
#include <vld.h>



using namespace std;
using std::cout;
using std::cin;

//global const declarations
const int NAME_COL_WIDTH = 30;
const int EMAIL_COL_WIDTH = 40;
const int MAX_TaskS = 100;

//function to read in user input as c-string
void readString (const char prompt[], char inputStr[], int maxChar)
{
    cin.get();//swallow the newline character if present
    cin.clear();
    //read until reaches the maxChar limit or encounters '\n'
    cout << prompt << endl;
    cin.get(inputStr, maxChar, '\n');
    while(!cin)
    {
        cin.clear ();
        cin.ignore (100, '\n');
        cout << prompt << endl;
        cin.get(inputStr, maxChar, '\n');
    }
    cout << endl;
}


int main() {
    //memory leak detection
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );


    const char * taskFile = "tasks.txt";
    char isInputCorrect;
    char menuSelection = 'x';

    //instantiate new TaskList object
    TaskList * myTaskList = new TaskList();
    //now we load our saved tasks into our new TaskList object
    (*myTaskList).loadTasks(taskFile);
    //tell the user how many tasks were read from memory
    cout << "After loading your file, you have " << (*myTaskList).getTotalTasks() << 
        " saved Tasks\n" << endl;

    while (true) { //menu loop

        cout << "Please choose from the following selections:" << endl;
        cout << "1. Enter a task or assignment" << endl;
        cout << "2. Display all of the tasks that are in the file" << endl;
        cout << "3. Find a task by course" << endl;
        cout << "4. Quit\n" << endl;
        cin >> menuSelection;

        if (menuSelection == '1') {

            char innerMenuSelection;
            char task[MAX_CHAR];
            int TaskSelection;

            do{
                char courseName[MAX_CHAR];
                char taskDescription[MAX_CHAR];
                char dueDate[MAX_CHAR];
                readString("Please enter the course name: ",
                    courseName,MAX_CHAR);
                readString("Please enter the task for this course: ",
                    taskDescription,MAX_CHAR);
                readString("Please enter the due date for this task,\nIn MM/DD/YYYY format: ",
                    dueDate,MAX_CHAR);
                //copy our attribute into our Task Object

                //add our task to our object 
                (*myTaskList).addTask(courseName, dueDate, taskDescription);
                cout << "You have entered " << courseName << " and " << 
                    taskDescription << endl;
                cout << "Enter Y if this input is correct, or anything else to re-enter:" 
                    << endl << endl;
                cin >> isInputCorrect;


            } while (isInputCorrect != 'Y');

        } else if (menuSelection == '2') {

            (*myTaskList).printAllTasks();

        } else if (menuSelection == '3') {

            char searchString[MAX_CHAR];
            int resultCount = 0;
            int indexOfFirstMatchingTask = 0;
            readString("Please enter the course name: ",
                searchString,MAX_CHAR);
            (*myTaskList).search(searchString, resultCount, 
                indexOfFirstMatchingTask);

        } else if (menuSelection == '4') {

            //we write our tasks to file to save for later use
            (*myTaskList).writeTasks("tasks.txt");
            break;
        }
    }

    //deletion of dynamically allocated mem
    delete myTaskList;

    return 0;
}

这是TaskList.cpp的副本:

#include "Task.h"
#include "TaskList.h"
#include <iostream>
#include <cstring>
#include <fstream>

using namespace std;

//custom default constructor
TaskList::TaskList() {
    totalTasks = 0;
    arrayOfTasks = new Task [MAX_CHAR];
}
bool TaskList::search(char * searchString, 
                      int &resultCount, int &indexOfFirstMatchingTask) {

                          resultCount = 0;//we reset resultCount if not passed with 0 value
                          bool isFound = false;
                          for (int i = 0; i < totalTasks+1; i++) {
                              if (strcmp(arrayOfTasks[i].getCourseName(), searchString) == 0) {
                                  resultCount++;
                                  cout << "You searched for: " << searchString << endl;
                                  cout << "So far, " << resultCount << 
                                      " match(es) have been found" << endl;
                                  cout << "The task for this matching course is: " << 
                                      endl << arrayOfTasks[i].getTaskDescription() << endl;
                                  isFound = true;
                              }
                          }

                          if(isFound == false) {
                              cout << "No match found for: " << searchString << endl;
                          }

                          cout << endl;
                          return isFound;
}
//function to write our tasks to file when closing the program
void TaskList::writeTasks(const char* fileName)
{ 
    ofstream        out;

    out.open (fileName);
    if(!out)
    {
        out.clear();
        cerr << endl << "Fail to open " << fileName << " for input!" << 
            endl << endl;
        exit(1);
    }

    for (int i = 0; i < totalTasks; i++) {
            if(i != totalTasks-1) {
            out << arrayOfTasks[i].getCourseName() << 
                ';' << arrayOfTasks[i].getTaskDescription() << 
                ';' << arrayOfTasks[i].getDueDate() << endl;
            } else {
                out << arrayOfTasks[i].getCourseName() << 
                ';' << arrayOfTasks[i].getTaskDescription() << 
                ';' << arrayOfTasks[i].getDueDate();
            }


        }   

    //close file
    out.close();
}

//function to load our saved tasks from file
void TaskList::loadTasks(const char* fileName)
{ 
    ifstream        in;
    char            name[MAX_CHAR];
    char            tasks[MAX_CHAR];
    char            dueDate[MAX_CHAR];

    in.open (fileName);
    if(!in)
    {
        in.clear();
        cerr << endl << "Fail to open " << fileName << " for input!" << 
            endl << endl;
        exit(1);
    }
    while (!in.eof())
    {
        in.get(name, MAX_CHAR, ';');        //read in Task name
        in.get();                           //remove field seperator ';'    
        in.get(tasks, MAX_CHAR, ';');       //read in task
        in.get();                           //remove field seperator ';'
        in.get(dueDate, MAX_CHAR, '\n');    //read in Task dueDate
        in.ignore(100, '\n');               //remove record seperator '\n'
        //incriment the total number of rows we have read and create new Task
        addTask(name, dueDate, tasks);
    }
    in.close();
}

//function to print all attributes of each task consecutively
void TaskList::printAllTasks() {
    for(int i = 0; i < totalTasks; i++) {
        //first we print the Task name
        cout << "Course name: " << endl;
        cout << arrayOfTasks[i].getCourseName();
        cout << endl;
        //now print the tasks for that Task
        cout << "Task description:" << endl;
        cout << arrayOfTasks[i].getTaskDescription();
        cout << endl;
        //now print due date
        cout << "Task due date:" << endl;
        cout <<  arrayOfTasks[i].getDueDate();
        cout << endl;
    }
    cout << endl;
}

//function to add a task
void TaskList::addTask(const char * courseName, const char * dueDate, 
        const char * taskDescription) {

    /*arrayOfTasks[totalTasks] = *new Task(courseName, dueDate, 
        taskDescription);*/
    totalTasks++;
}

//function to return the current number of tasks
int TaskList::getTotalTasks() { 
    return totalTasks;
}

//function to print c-string
void TaskList::cStringPrint(char * arrayToPrint){
    if(*arrayToPrint != '\0'){ //can alternatively swap '\x0' for NULL
        cout << *arrayToPrint;
        arrayToPrint++;
        //recursive tail call on next element address
        cStringPrint(arrayToPrint);
    }
}

//destructor to delete all dynamically allocated memory
TaskList::~TaskList() {
    delete[] arrayOfTasks;
    arrayOfTasks = NULL;
}

以下是我收到的错误的副本: enter image description here

1 个答案:

答案 0 :(得分:1)

在writeTasks中,如果无法打开文件,则打印错误(我可以在上面的命令提示符中看到),然后退出!所以当然一​​切都泄漏了。

我认为,最好的办法就是避免在发生不良事件时调用退出:使用更强大的错误处理方案(如异常)。