方法返回后内存被破坏

Memory being corrupted after method returns

本文关键字:内存 返回 方法      更新时间:2023-10-16

我知道我只是错过了一些愚蠢的东西,但我很沮丧,我就是看不见它。当我对一个包含3个字段的文件运行下面的代码"field1;field2;field3"时,任务在retrieveTasks方法中被正确地打印出来。当该方法返回到main时,输出已损坏。我知道这很愚蠢,我只是想念它。我试过将CourseName, TaskDescription等改为数组而不是char*。我已经尝试过将fileString作为char*传入,我已经尝试过strcpy和没有。有人能给我指个方向吗?

const int MAX_STRING_LENGTH = 101;
const int MAX_TASK_ITEMS = 255;
const char NEWLINE = 'n';
const char DELIMETER[] = ";";
const char FILENAME[] = "tasks.txt";
struct Task {
  char* CourseName;
  char* TaskDescription;
  char* DueDate;
  char FileString[300];
  void printTask() {
    cout << CourseName << DELIMETER << TaskDescription << DELIMETER  << DueDate << endl;
  }
  void initializeFromFileString(char fileString[]) {
    strcpy(FileString, fileString);
    CourseName = strtok(FileString, DELIMETER);
    TaskDescription = strtok(NULL, DELIMETER);
    DueDate = strtok(NULL, DELIMETER);
  }
};
struct TaskList {
  Task Tasks[MAX_TASK_ITEMS];
  int TaskCount;
  void initialize() {
    TaskCount = 0;
    return;
  }
  void addTask(Task task) {
    Tasks[TaskCount] = task;
    TaskCount++;
    return;
  }
  void printTasks() {
    for(int TaskNum = 0; TaskNum < TaskCount; TaskNum++) {
      cout << TaskNum + 1 << ".      ";
      Tasks[TaskNum].printTask();
      cout << endl;
    }
    return;
  }
  // Load data from the file. Will return -1 if it fails for any reason.
  // Otherwise it returns the number of records read.
  int retrieveTasks(const char* fileName) {
    int isSuccessfulOpen = 0;
    int recordsRead = 0;
    ifstream inFile;
    isSuccessfulOpen = openFile(inFile, fileName);
    if(!isSuccessfulOpen) {
      return -1;
    }
    // Read input file and store in appropriate arrays
    while(inFile.eof() == false) {
      char fileLine[MAX_STRING_LENGTH * 3];
      Task task;
      inFile.getline(fileLine, MAX_STRING_LENGTH * 3, NEWLINE);
      inFile.ignore(UINT_MAX, NEWLINE);
      task.initializeFromFileString(fileLine);
      addTask(task);
      recordsRead++;
    }
    inFile.close();
    return recordsRead;
  }
};
int main() {
  bool isFinished = false;
  TaskList taskList;
  taskList.initialize();
  taskList.retrieveTasks(FILENAME);
  taskList.printTasks();
  return 0;
}

int openFile(ifstream& inFile, const char* fileName) {
  inFile.open(fileName);
  // Veryify that the file is valid. If not print error message.
  if(inFile.is_open() == false) {
    cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
    return 0;
  }
  return 1;
}
// Open file for writing
int openFile(ofstream& outFile, const char* fileName) {
  outFile.open(fileName);
  // Veryify that the file is valid. If not print error message and exit.
  if(outFile.is_open() == false)
  {
    cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
    return 0;
  }
  return 1;
}

CourseName, TaskDescription, DueDate都指向在while循环中创建的task对象中存在的数组中的内存。由于task对象是局部作用域,一旦retrieveTasks完成执行,它们就会包含垃圾。

更改需要

  1. 你的任务计数总是比计数多一个-因此这个需要减少1。

    for(int TaskNum = 0; TaskNum < TaskCount; TaskNum++) {
    

    更改为

    for(int TaskNum = 0; TaskNum < TaskCount -1 ; TaskNum++) {
    
  2. 从while循环中删除Task对象

  3. AddTask接受char *而不是Task。AddTask调用initializeFromFileString,使strcpy对数组的Task对象内的字符串完成。strtok也在字符串

  4. 上被调用改变
  5. while(inFile.eof() == false) {
    

    while(inFile) {
    
  6. 删除
    inFile.ignore(UINT_MAX, NEWLINE);
    

固定代码
struct Task {
  char* CourseName;
  char* TaskDescription;
  char* DueDate;
  char FileString[300];
  void printTask() {
    cout << CourseName << DELIMETER << TaskDescription << DELIMETER  << DueDate << endl;
  }
  void initializeFromFileString(char fileString[]) {
    strcpy(FileString, fileString);
    CourseName = strtok(FileString, DELIMETER);
    TaskDescription = strtok(NULL, DELIMETER);
    DueDate = strtok(NULL, DELIMETER);
  }
};

int openFile(ifstream& inFile, const char* fileName) {
  inFile.open(fileName);
  // Veryify that the file is valid. If not print error message.
  if(inFile.is_open() == false) {
    cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
    return 0;
  }
  return 1;
}
// Open file for writing
int openFile(ofstream& outFile, const char* fileName) {
  outFile.open(fileName);
  // Veryify that the file is valid. If not print error message and exit.
  if(outFile.is_open() == false)
  {
    cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
    return 0;
  }
  return 1;
}
struct TaskList {
  Task Tasks[MAX_TASK_ITEMS];
  int TaskCount;
  void initialize() {
    TaskCount = 0;
    return;
  }
  void addTask(char * t) {
    Tasks[TaskCount].initializeFromFileString(t);
    TaskCount++;
    return;
  }
  void printTasks() {
    for(int TaskNum = 0; TaskNum < TaskCount - 1; TaskNum++) {
      cout << TaskNum + 1 << ".      ";
      Tasks[TaskNum].printTask();
      cout << endl;
    }
    return;
  }
  // Load data from the file. Will return -1 if it fails for any reason.
  // Otherwise it returns the number of records read.
  int retrieveTasks(const char* fileName) {
    int isSuccessfulOpen = 0;
    int recordsRead = 0;
    ifstream inFile;
    isSuccessfulOpen = openFile(inFile, fileName);
    if(!isSuccessfulOpen) {
      return -1;
    }
    // Read input file and store in appropriate arrays
    while(inFile) {
      char fileLine[MAX_STRING_LENGTH * 3];
      inFile.getline(fileLine, MAX_STRING_LENGTH * 3, NEWLINE);
      addTask(fileLine);
        printTasks();
      recordsRead++;
    }
    inFile.close();
    return recordsRead;
  }
};

很明显,如果你用C++而不是C inside classes来写,整个程序会更简单,更少出错。