无法隔离内存泄漏
Can not isolate memory leak
我正在使用 Visual Studio 泄漏检测工具:https://visualstudiogallery.msdn.microsoft.com/7c40a5d8-dd35-4019-a2af-cb1403f5939c
这给了我泄漏的行号,因为我一辈子都无法得到 #define _CRTDBG_MAP_ALLOC
来为我提供描述性输出。如果您发现我在我的代码中使用不正确,请说出来,我想知道如何正确使用它,但就目前而言,可视化泄漏检测工具运行良好。
我不断发现 2 个内存泄漏,一个在 project4.cpp 第 58 行,另一个在 tasklist.cpp 第 13 行。
第一个泄漏,project4.cpp 第 58 行,当我调用 delete myTaskList
.[=17 时,应该由我主函数的 return 语句之前的 delete 语句密封=]
第二次泄漏,taskList.cpp 第 13 行,当我的 TaskList class 的重写析构函数如此调用时应该被密封:
//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 != '[=12=]'){ //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;
}
这是我收到的错误的副本:
在 writeTasks 中,如果无法打开文件,则打印错误(我可以在上面的命令提示符中看到),然后退出!所以当然一切都会泄漏。
在我看来,最好的办法是避免在发生错误时调用 exit:使用更强大的错误处理方案(如异常)。
我正在使用 Visual Studio 泄漏检测工具:https://visualstudiogallery.msdn.microsoft.com/7c40a5d8-dd35-4019-a2af-cb1403f5939c
这给了我泄漏的行号,因为我一辈子都无法得到 #define _CRTDBG_MAP_ALLOC
来为我提供描述性输出。如果您发现我在我的代码中使用不正确,请说出来,我想知道如何正确使用它,但就目前而言,可视化泄漏检测工具运行良好。
我不断发现 2 个内存泄漏,一个在 project4.cpp 第 58 行,另一个在 tasklist.cpp 第 13 行。
第一个泄漏,project4.cpp 第 58 行,当我调用 delete myTaskList
.[=17 时,应该由我主函数的 return 语句之前的 delete 语句密封=]
第二次泄漏,taskList.cpp 第 13 行,当我的 TaskList class 的重写析构函数如此调用时应该被密封:
//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 != '[=12=]'){ //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;
}
这是我收到的错误的副本:
在 writeTasks 中,如果无法打开文件,则打印错误(我可以在上面的命令提示符中看到),然后退出!所以当然一切都会泄漏。
在我看来,最好的办法是避免在发生错误时调用 exit:使用更强大的错误处理方案(如异常)。