使用exception :: what()时由cout打印的多余字符

时间:2011-11-29 08:07:34

标签: c++

我确信这很简单,但我无法设计一个帮助我解决问题的搜索查询。

我几乎倾向于认为这是Windows命令提示符中的一个错误,除了之前我从未见过它,直到我开始使用异常,当且仅当我使用异常时才会发生异常:: what ()。

这是一个家庭作业,该程序应该计算一系列给定的问题并显示答案。所有问题都是类似的(矩阵/向量算法),唯一导致问题的是有意设计产生错误的问题,因为这是唯一的时间例外:: what()。

这是一个令人不快的问题:

(顺便说一句,任意放置这些都可以 问题进入块,以便对象超出范围,并在下一个问题之前调用析构函数,就像我已经完成的那样?)

{ // Problem #9
    Vector v1(5);
    Matrix m1(3, 3, 1);
    try {
        v1.set(1, -2);
        v1.set(2, -1);
        v1.set(3, 4);
        v1.set(4, 9);
        v1.set(5, 3);
        m1.set(1, 1, 12);
        m1.set(1, 2, 36);
        m1.set(1, 3, -7);
        m1.set(2, 1, 4);
        m1.set(2, 3, 11);
        m1.set(3, 1, 7);
        m1.set(3, 2, -5);
        m1.set(3, 3, -2);
        Vector * ans9 = product(m1, v1);
        cout << "Answer to problem 9:" << endl;
        ans9->print();
        delete ans9;
    }
    catch(exception & ex) {
        cout << "Exception in problem 9: " << ex.what() << endl;
    }
} // End problem 9
cout << endl << endl;

Matrix类及其构造函数没什么特别的,代码不会抛出任何异常,所以我只会分享有问题的product()函数:

Vector * product(Matrix &m, Vector &v) {
    unsigned int vLength = v.getLength(), mRows = m.getRows(), mCols = m.getCols();
    if ( mCols != vLength ) {
            throw std::logic_error("matrix/vector product impossible (size mismatch)!");
    }
    Vector * vprod = new Vector(mRows);
    for (unsigned int i = 1; i <= mRows; ++i) {
        double value = 0;
        for (unsigned int j = 1; j <= vLength; ++j) {
            value += (m.get(i, j)) * (v.get(j));
        }
        vprod->set(i, value);
    }

    return vprod;
}

这是我得到的输出类型的一个例子:

screenshot http://img827.imageshack.us/img827/7328/wtfuz.png

我离开了!在那里你可以看到它只是打印那个列上的最后一个字符,直到那里明确地印有其他字符。

那么,到底发生了什么?我认为它可能与字符串终止有关,但也许这只是因为我过去对C有太多的乐趣。

编辑:人们要求提供可编辑的代码段,我能做的最好的就是228行。这是:

#include <iostream>
#include <iomanip>
#include <cstdlib>

using std::cout;
using std::endl;
using std::exception;

class Vector {
    private:
    unsigned int length;
    double *elements;

    public:
    Vector(unsigned int desiredLength);

    ~Vector();

    //void dDestroy(Vector &v);

    unsigned int getLength();

    void set(unsigned int position, double value);

    double get(unsigned int position);

    void print();
};

Vector::Vector(unsigned int desiredLength) {
    length = desiredLength;
    elements = new double[length];
    for (unsigned int i = 0; i < length; ++i) {
        elements[i] = 0;
    }
}

Vector::~Vector() {
    delete[] elements;
}

unsigned int Vector::getLength() {
    return length;
}                    

void Vector::set(unsigned int position, double value) {
    if (position > length || position <= 0) {
        throw std::logic_error("vector set failed (out of range)");
    }
    --position;
    elements[position] = value;
}

double Vector::get(unsigned int position) {
    if (position > length || position <= 0) {
        throw std::logic_error("vector get failed (out of range)");
    }
    --position;
    return elements[position];
}

void Vector::print() {
    std::cout << "[  ";
    for (unsigned int i=0; i < length; ++i) {
        std::cout << elements[i] << "  " ;
    }
    std::cout << "]";
}

class Matrix {
    private:
    unsigned int rows, cols;
    double **elements;

    public:

    Matrix(unsigned int desiredRows, unsigned int desiredCols, double defaultValue);

    ~Matrix();

    unsigned int getRows();

    unsigned int getCols();

    void set(unsigned int i, unsigned int j, double value);

    double get(unsigned int i, unsigned int j);

    void print();
};

Matrix::Matrix(unsigned int desiredRows, unsigned int desiredCols, double defaultValue) {
    rows = desiredRows, cols = desiredCols;
    // Create
    elements = new double*[rows];
    for (unsigned int i = 0; i < rows; ++i) {
        elements[i] = new double[cols];
    }
    // Initialize
    for (unsigned int i = 0; i < rows; ++i) {
        for (unsigned int j = 0; j < cols; ++j) {
            elements[i][j] = defaultValue;
        }
    }
}

Matrix::~Matrix() {
    for (unsigned int i = 0; i < rows; ++i) {
        delete[] elements[i];
    }
    delete[] elements;
}

unsigned int Matrix::getRows() {
    return rows;
}

unsigned int Matrix::getCols() {
    return cols;
}

void Matrix::set(unsigned int i, unsigned int j, double value) {
    if (i > rows || j > cols) {
        throw std::logic_error("matrix set failed (out of range).");
    }
    --i, --j;
    elements[i][j] = value;
}

double Matrix::get(unsigned int i, unsigned int j) {
    if (i > rows || j > cols || i <= 0 || j <= 0) {
        throw std::logic_error("matrix get failed (out of range).");
    }
    --i, --j;
    return elements[i][j];
}

void Matrix::print() {
    // TODO it would be nice to format based on maximum digits in any value
    for (unsigned int i = 0; i < rows; ++i) {
        std::cout << "[  ";
        for (unsigned int j = 0; j < cols; ++j) {
            std::cout << std::setprecision(2) << elements[i][j] << "  ";
        }
        std::cout << "]\n";

    }
}

Vector * dot(Vector &v1, Vector &v2) {
    if (v1.getLength() != v2.getLength() ) {
        throw std::logic_error("dot product impossible (length mismatch)");
    }
    double result = 0;
    for (unsigned int i = 1; i <= v1.getLength(); ++i) {
        result += (v1.get(i) * v2.get(i));
    }
    Vector * vdot = new Vector(1);
    vdot->set(1, result);
    return vdot;
}

Vector * product(Matrix &m, Vector &v) {
    unsigned int vLength = v.getLength(), mRows = m.getRows(), mCols = m.getCols();
    if ( mCols != vLength ) {
        throw std::logic_error("matrix/vector product impossible (size mismatch)");
    }
    Vector * vprod = new Vector(mRows);
    for (unsigned int i = 1; i <= mRows; ++i) {
        double value = 0;
        for (unsigned int j = 1; j <= vLength; ++j) {
            value += (m.get(i, j)) * (v.get(j));
        }
        vprod->set(i, value);
    }

    return vprod;
}

Vector * dot(Vector &v1, Vector &v2);
Vector * product(Matrix &m, Vector &v);

int main() {
    cout << endl;

    { // Problem #1
    Vector v1(3), v2(3);
    try {
        v1.set(1, 2);
        v1.set(2, 1);
        v1.set(3, 3);
        v2.set(1, 0);
        v2.set(2, 4);
        v2.set(3, -9);

        Vector * ans1 = dot(v1, v2);
        cout << "Answer to problem 1:" << endl;
        ans1->print();
        delete ans1;
    }

    catch(const exception & ex) {
        cout << "Exception in problem 1: " << ex.what() << endl;
    }
    } // End problem 1
    cout << endl << endl;


    { // Problem #2
    Vector v1(2), v2(3);
    try {
        v1.set(1, 12);
        v1.set(2, 1);
        v2.set(1, 3);
        v2.set(2, -1);
        v2.set(3, 5);
        Vector * ans2 = dot(v1, v2);
        cout << "Answer to problem 2:" << endl;
        ans2->print();
        delete ans2;
    }
    catch(const exception & ex) {
        cout << "Exception in problem 2: " << ex.what() << endl;
    }

    } // End problem 2
    cout << endl << endl;
}

2 个答案:

答案 0 :(得分:1)

好的,评论有点慌张,以下内容对于评论有点明确,所以请原谅以下不完全答案的风格。

因为额外的“!”在程序已经退出之后,也有可能与你的应用程序有关。它可能是一个错误的显示驱动程序,或客户端服务器运行时子系统/进程(csrss.exe)或控制台Windows主机(conhost.exe)的一些问题,它们在您运行控制台应用程序时提供窗口。 此外,如果截图不是误导性的,那么看起来像超级字符(特别是“问题6”中的右括号可见)甚至不能完全重复,而只是部分重复。即这个角色以某种方式被“削减”。

无论如何,您可以尝试进一步调查问题:

  1. 它只发生在您的系统上吗?
  2. 它是否只发生在64位进程中(我假设你有一个来自CMD标题)
  3. 如果您实际上没有抛出异常,也会发生这种情况,例如

    std :: logic_error err(“blah”);    std :: cout&lt;&lt; err.what()&lt;&lt;的std :: ENDL;

  4. 您可以将程序更改为使用stdio而不是iostream吗?它是否仍然会发生。

  5. 尝试将程序的输出重定向到文件(例如“myapp.exe&gt; foo.txt”)。该文件是否还包含额外的“!”。

  6. 我在完全不同的情况下看到了这种行为。

    示例:

    printf("12345678901234567890\r"); /* carriage return, but no linefeed */
    printf("ABCDEFGHIJ\n");
    

    这应输出:

    ABCDEFGHIJ1234567890
    

    但是,在我的代码中,我没有看到类似的内容(iostreams与stdio相关)。

答案 1 :(得分:0)

它让我担心你会遇到'异常&amp;'而不是'const exception&amp;'。 'ex'实际上可能引用已经被销毁的对象,因此what()方法返回垃圾。您必须确保catch-handler中的'ex'参数引用最初抛出的对象的有效副本。