0

基本上,下面是我的 main.cpp,当我尝试使用 Qt 的调试器运行它时,我得到“EXC_BAD_ACCESS”错误(“无法访问内存”)以及 main 第一行旁边的箭头(它说Puzzle puzzle;) . 我认为这可能是我的 Puzzle 类的问题,但是当我将该行移到其他地方时,我仍然遇到错误的访问错误,调试器在main. 是什么导致了这个错误?我的程序半小时前运行良好,然后开始抛出这个错误,我什至没有修改代码,因为它上次工作。此外,这是我在 C/C++ 中的第一个项目之一,所以我对垃圾收集并不完全熟悉。这可能与内存泄漏或内存分配错误有关吗?

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include "piece.h"
#include "puzzle.h"
#include "state.h"


using namespace std;

//function prototypes
Puzzle initPuzzle(string*, int);
int countWords(string);

//count the number of words (separated by white space) in a string
int countWords(string s){
    int words = 0;
    char * temp = new char[s.size() + 1];
    copy(s.begin(), s.end(), temp);
    temp[s.size()] = '\0';
    temp = strtok (temp, " ");
    while (temp != NULL){
        words++;
        temp = strtok (NULL, " ");
    }
    delete(temp);
    return words;
}


//first checks validity of input
//if error(s), display appropriate message & exit program
//otherwise, returninstance of puzzle class from input file
//params: lines = array of strings, each of which is a line from input... size = # of elems in 'lines'
Puzzle initPuzzle(string * lines, int size){
    //create instance of puzzle
    //if bad piece found, throw it out
    //if first piece (Z) is invalid, the next piece becomes goal piece
    //if there are 0 valid pieces, display error to user and exit program
    Puzzle ret;
    int rows, cols;
    if(size < 2){
        //not enough lines for valid input
        cout << "Error: Input too short" << endl << "Exiting program..." << endl;
        exit(0);
    }
    istringstream iss(lines[0]);
    if((iss >> rows >> cols) && countWords(lines[0])==2){
        ret.rows=rows;
        ret.cols=cols;
    } else {
        cout << "Error: Invalid first line" << endl << "Exiting program..." << endl;
        exit(0);
    }
    if(rows < 1 || cols < 1){
        cout << "Error: Invalid dimensions" << endl << "Exiting program..." << endl;
        exit(0);
    }

    //now check the rest of the lines (ie the pieces)
    for(int i=1; i<size; i++){
        Piece newPiece;
        int startRow, startCol, width, height;
        char direction;
        istringstream iss(lines[i]);
        if(countWords(lines[i])==5 && (iss >> startRow >> startCol >> width >> height >> direction)){
            //row is formatted correctly, create instance of Piece
            newPiece = Piece(startRow, startCol, width, height, direction); //validate this piece later... if valid, add to pieces
        } else {
            //invalid row... entire input is invalid
            cout << "Error: Invalid row(s)" << endl << "Exiting program..." << endl;
            exit(0);
        }
        //now validate temporary piece...
        //first make sure piece doesn't fall outside of grid
        if(newPiece.startRow < 1 || newPiece.startCol < 1 || newPiece.startRow-1 > (rows - newPiece.height) ||
                newPiece.startCol-1 > (cols - newPiece.width)){
            //newPiece goes over the edge of the puzzle grid
            cout << "Piece goes beyond grid... Throwing it out" << endl;
            continue;
        }
        if(newPiece.direction != 'b' && newPiece.direction != 'h' && newPiece.direction != 'v' && newPiece.direction !='n'){
            //newPiece has invalid direction
            cout << "Piece has invalid direction... Throwing it out" << endl;
            continue;
        }
        if(ret.pieceCount!=0 && ret.pieceOverlap(newPiece)){
            //current piece overlaps existing one
            cout << "Piece overlaps another piece... Throwing it out" << endl;
            continue;
        }
        //if loop iteration reaches this point, piece is valid and can be added to puzzle
        cout << "Piece is good!" << endl;
        ret.addPiece(newPiece);
    }
    if(ret.pieceCount == 0){
        //all pieces were invalid
        cout << "Error: Puzzle has no pieces" << endl << "Exiting program..." << endl;
        exit(0);
    }

    //now assign id's to the pieces...
    for(int i=0; i<ret.pieceCount; i++){
        if(i==0){
            ret.pieces[i].id = 'Z';
        } else {
            ret.pieces[i].id = i;
        }
    }

    return ret;
}

int main()
{
    Puzzle puzzle;                              //single instance of puzzle class... initialized later after input & piece verification
    string inputFile;                           //name of input file... provided by user
    string line;                                //single line from input file
    string * inputLines = new string[9000];     //array of lines from the input file
    ifstream infile;
    int size = -1;                              //size of inputLines array, initialized to -1

    cout << "Enter name of input file: ";
    cin >> inputFile;
    infile.open(inputFile.c_str());
    if(infile){
        while(infile){
            size++;
            getline(infile,line);
            inputLines[size] = line;
        }
        infile.close();
    } else {
        cout << "Error: Input file could not be opened" << endl << "Exiting program" << endl;
        exit(0);
    }

    puzzle = initPuzzle(inputLines, size);  //now check the input for validity, and if valid, initialize puzzle


    return 0;
}
4

1 回答 1

3

一个错误(实际上是两个)在函数中countWords()

  • temp使用创建new[]但释放使用delete,它必须是delete[]new->deletenew[]->delete[]并尽可能避免显式动态内存管理)
  • 的值temp不是最初分配的值,它在ingdelete[]时必须是

std::istringstream通过使用 a来计算单词,可以完全避免显式动态内存分配:

std::istringstream in(s);
std::string ignored;
while (in >> ignored) words++;

其他要点:

  • 更喜欢std::vector显式动态内存分配管理:

    std::vector<std::string> inputLines; // and use 'push_back()'.
    
  • 始终立即检查输入操作的结果以确保成功:

    if (cin >> inputFile)
    {
        ifstream infile(inputFile);
        if (infile)
        {
            std::string line;
            while (std::getline(infile, line)) lines.push_back(line);
        }
    }
    
于 2013-02-20T21:22:52.357 回答