创建Object时,Debug Assertion失败

时间:2014-02-21 15:35:30

标签: c++ constructor reference

我正在尝试为大学构建一个简单的矩阵代数应用程序。尝试从输入文件添加数据时,我使用以下方法:

Matrix createMatrix(string filename, int rowRestriction, int colRestriction)
{
    try{
    ifstream file;
    string line = "";
    vector<string> curLine;
    int cols = -1, rows = 0;
    vector<vector<double>> values;
    file.open(filename);
    if(!file.is_open())
    {
        cout << "No file could be loaded, please check whether the input file is placed inside the working directory.\n";
        throw 1;
    }
    while(getline(file,line))
    {
        rows+=1;
        curLine = split(line);
        if(cols == -1)
        {
            cols = curLine.size();
            cout << "Matrix appears to have " << cols << " Columns.\n";
            if(colRestriction != NO_RESTRICTION && cols != colRestriction)
            {
                cout << "The Matrix you provided does not fulfill the column restriction of " << colRestriction << " Columns, please check your input file.\n";
                throw 2;
            }
        }
        else if(cols != curLine.size())
        {
            cout << "Invalid Matrix supplied. Varying amount of columns. Please check input file " << filename << ".\n";
            throw 3;
        }
            cout << "Saving Row "<<rows<<"\n";
            values.resize(rows);
            values[rows-1].resize(cols);
            for(int i = 0; i < curLine.size(); i++)
            {
                if(isValidNumber(curLine[i]))
                    try
                    {
                        values[rows-1][i] = atof(curLine[i].c_str());
                    }
                    catch(int e)
                    {
                        cout << "Exception No. " << e << " has occurred. Presumably your input file does not contain valid floating point numbers.\n";
                        throw 4;

                    }
                else
                {
                    cout << "Your file contains invalid characters, please check your input file \"" << filename << "\".\n";
                    throw 5;
                }
            }
    }
    if(rowRestriction != NO_RESTRICTION && rowRestriction != rows)
    {
        cout << "The Matrix you provided does not fulfill the row restriction of " << rowRestriction << " Rows, please check your input file.\n";
        throw 6;
    }
    cout << "Matrix Data has been read successfully, your matrix has " << rows << " Rows and " << cols << " Columns. It is " << ((rows==cols)?"":"not ") << "quadratic.\n";
    Matrix m = Matrix(rows, cols, values);
    m.setValidity(true);
    return m;
    }
    catch(int e)
    {
        cout << "Exception No. " << e << "occurred.\n";
    }
}

这是'Matrix'的构造函数:

Matrix::Matrix(int rows, int cols, vector<vector<double>> data)
{
    this->rows = rows;
    this->cols = cols;
    this->data = data;
}

这是头文件:

#pragma once
#include <vector>
using std::vector;
class Matrix
{
public:
    Matrix(int rows, int cols, vector<vector<double>> data);
    ~Matrix(void);
    int getCols();
    int getRows();
private:
    int rows, cols;
    vector<vector<double>> data;
};

我收到以下错误消息 - 仅在添加行Matrix m = Matrix(rows, cols, values);时显示(见上文)。

    ---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Debug Assertion Failed!

Program: ...al studio 2012\Projects\Matrixalgebra\Debug\Matrixalgebra.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line: 1322

Expression: _CrtIsValidHeapPointer(pUserData)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

---------------------------
Abort   Retry   Ignore   
---------------------------

我只是知道这是一个新手的错误,但我已经尝试了很长一段时间但没有成功。算法本身可以正常工作,直到最后几行。

编辑:更改了OP以反映新问题

EDIT2:因为我的解构函数而抛出此新错误,请参阅下文

Matrix::~Matrix(void)
{
    delete &data;
}

为什么会这样 - 我真的很感激这方面的解释,或者有关此问题的一些学习材料。

3 个答案:

答案 0 :(得分:1)

您的问题是您在“createMatrix”函数中返回局部变量的地址。

为什么createMatrix会返回Matrix *?你避免使用指针,直到那时为止。你的createMatrix应该返回一个Matrix对象,而不是一个指针。

Matrix createMatrix(string filename, int rowRestriction, int colRestriction)
{
    //....
    Matrix m = //;
    return m;
}

这就是我所期望的,或类似的东西。

答案 1 :(得分:1)

问题在于:

Matrix *createMatrix(string filename, int rowRestriction, int colRestriction) {  
    // ...
    Matrix m = Matrix(rows, cols, values);
    return &m;
}

您正在返回指向函数内堆栈上创建的变量的指针。当函数返回时,该指针将无效并使用它将导致未定义的行为。幸运的是,调试运行时通过抛出一个断言来告诉你。

(编辑)用于发出错误信号的可能解决方案:

一个。动态分配矩阵的存储空间

Matrix *createMatrix(string filename, int rowRestriction, int colRestriction) { 
  // ... 
  Matrix *m = new Matrix(rows, cols, values); 
  return &m; 
}

优点:做你想做的,不需要改变你的代码

缺点:在堆上创建一个矩阵,谁将要释放它?

B中。修改你的功能

bool loadMatrixFromFile(string filename, int rowRestriction, int colRestriction, Matrix& m) { 
  // ... 
  // If something goes wrong -> return false
  Matrix newMatrix(rows, cols, values); 
  m = newMatrix;
  return true; 
}

// Call like this:
Matrix m;
bool retVal = loadMatrixFromFile("",bla , bla, m);

优点:我认为这是一种可以推荐的方式,避免了在无法使用RVO时复制矩阵的开销,允许您发出错误信号。另外:功能名称现在还描述了它的实际功能: - )

缺点:没有我能想到的。

答案 2 :(得分:0)

这是绝对的反模式:从驻留在autoamtic内存中的ab对象返回指针(或引用),即在堆栈上。在返回之后发生的下一件事,它会破坏变量内容 - 任何东西。

Matrix * x(...){
    ...
    Matrix m = ...;
    return &m;
}

在您的情况下,您可以使用new并返回指向堆上的一块动态内存的指针:

    Matrix * m = new Matrix( nrow,... );
    return m;