/* * This is a very badly broken C++ program. Its purpose in life is to * illustrate some basic debugging concepts. Comments have been kept * to a minimum because the code will be explained in class, and so * that the maximum amount of information will fit on the display. */ #include #include #include using namespace std; int main(int argc, char* argv[]); // Matrix multiplier static void usage(char* progname); // Issue a usage message static double** makeMatrix(int rows, int columns, bool initWell); // Create a test matrix static void zapMatrix(double** matrix, int rows, int columns); // Free a matrix static void matrixMultiply(double** dest, double** m1, double** m2, int r1, int c1, int r2, int c2); // Do matrix multiplication static void printMatrix(ostream& stream, double** matrix, int rows, int columns); // Print a matrix to a stream int main( int argc, // Number of arguments char* argv[]) // Vector of argument strings { if (argc != 4) // BUG: Wrong constant usage(argv[0]); int r1 = atoi(argv[1]); int r2 = atoi(argv[2]); // BUG: should be c1 int c1 = atoi(argv[3]); // BUG: should be r2 int c2 = atoi(argv[4]); double** m1 = makeMatrix(r1, c1, true); double** m2 = makeMatrix(r2, c1, true); // BUG: should be c2 double** m3 = makeMatrix(r1, c2, false); cout << "Matrix 1:\n"; printMatrix(cout, m1, r1, c1); cout << "\nMatrix 2:\n"; printMatrix(cout, m2, r2, c2); zapMatrix(m1, r1, c1); // BUG: freed too early zapMatrix(m2, r1, c1); // BUG: should be r2/c2 matrixMultiply(m3, m1, m2, r1, c1, r2, r2); // BUG: r2 instead of c2 cout << "\nResult:\n"; printMatrix(cout, m3, r1, c2); zapMatrix(m3, r1, c2); return 0; } static void usage( // Issue a usage message char* progname) // Name we were run under { cerr << "Usage: " << progname << " r1 c1 r2 c2"; // BUG: no newline exit(2); } static double** makeMatrix( // Create a test matrix int rows, // Number of rows in matrix int columns, // Number of columns in matrix bool initWell) // True to initialize usefully { double** matrix = new double*(rows); // BUG: should be [] for (int i = 0; i < rows; i++) { matrix[i] = new double[columns]; for (int j = 0; j < columns; j++) { if (initWell) matrix[i][j] = i * columns + j; else matrix[i][j] = time((time_t*) NULL) + i + j; } } return matrix; } static void zapMatrix( // Free a matrix double** matrix, // Matrix to delete int rows, // Number of rows in matrix int ) // Number of columns in matrix { for (int i = 0; i < rows; i++) delete matrix[i]; // BUG: should be delete[] delete matrix; // BUG: should be delete[] } static void matrixMultiply( // Multiply matrices double** dest, // Space for result double** m1, // Left operand double** m2, // Right operand int r1, // Rows in left operand int c1, // Columns in left operand int r2, // Rows in right operand int c2) // Columns in right operand { if (r1 != c2) // BUG: should be c1 != r2 { cerr << "Can't multiply nonconformal matrices\n"; exit(1); } for (int i = 0; i < r1; i++) { for (int j = 0; j < c2; j++) { double sum; // BUG: uninitialized variable for (int k = 0; k < c1; k++) sum += m1[i][k] * m2[k][j]; // BUG: forgot to put sum in dest[i][j] } } } static void printMatrix( // Print a matrix to a stream ostream& stream, // Stream to print to double** matrix, // Matrix to print int rows, // Number of rows in matrix int columns) // Number of columns in matrix { for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if (j != 0) stream << ' '; stream << matrix[i][j]; } stream << '\n'; } }