Từ 1 tới 7 trên tổng số 7 kết quả

Đề tài: Lỗi bộ nhớ trong lớp xử lý ma trận

  1. #1
    Ngày gia nhập
    12 2007
    Bài viết
    48

    Arrow Lỗi bộ nhớ trong lớp xử lý ma trận

    Cho em hỏi code này em sai gì?

    1) Em nghĩ bị lỗi bộ nhớ là do trả về đối tượng temp(cái mà có mảng động bị delete khi kết thúc hàm), nhưng em nghĩ muốn cộng 2 ma trận thì phải tạo đối tượng tạm rồi trả về, để gán vào đối tượng kết quả.

    2) Làm ơn chỉ em cách khắc phục. Em cảm ơn nhiều lắm lắm.

    C++ Code:
    1. #include <iostream>
    2. using std::cout;
    3. using std::cin;
    4. using std::endl;
    5. using std::istream;
    6. using std::ostream;
    7. #include <iomanip>
    8. using std::setw;
    9.  
    10. class Matrix
    11. {
    12.     friend istream &operator>>(istream &input, Matrix &m);
    13.     friend ostream &operator<<(ostream &output, const Matrix &m);
    14.     public:
    15.         Matrix(int r, int c);
    16.         ~Matrix();
    17.         void setMatrix(int r, int c);
    18.         void initMatrix();
    19.         const bool operator==(const Matrix &right) const;  
    20.         const Matrix operator+(const Matrix &right);
    21.         const Matrix &operator=(const Matrix &right);
    22.        
    23.     private:
    24.         int **ptr;
    25.         int row, col;
    26. };
    27.  
    28. Matrix::Matrix(int r, int c)
    29. {  
    30.     setMatrix(r, c);
    31. }
    32.  
    33. void Matrix::setMatrix(int r, int c)
    34. {
    35.     row = r;
    36.     col = c;
    37.  
    38.     // allocation //
    39.     ptr = new int *[row];
    40.     for(int i = 0; i < row; i++)
    41.         ptr[i] = new int [col];
    42.  
    43.     // initialization //
    44.     initMatrix();
    45. }
    46.  
    47. void Matrix::initMatrix()
    48. {
    49.     for(int i = 0; i < row; i++)
    50.         for(int j = 0; j < col; j++)
    51.             ptr[i][j] = 0;
    52. }
    53.  
    54. // deallocation //
    55. Matrix::~Matrix()
    56. {
    57.     for(int i = 0; i < row; i++)
    58.         delete []ptr[i];
    59.     delete []ptr;
    60.     cout << "Object was deleted" << endl;
    61. }
    62.  
    63. istream &operator>>(istream &input, Matrix &m)
    64. {
    65.     for(int i = 0; i < m.row; i++)
    66.         for(int j = 0; j < m.col; j++)
    67.         {
    68.             cout << "Enter element[" << i << "][" << j << "]: ";
    69.             input >> m.ptr[i][j];
    70.         }
    71.     return input;
    72. }
    73.  
    74. ostream &operator<<(ostream &output, const Matrix &m)
    75. {  
    76.     for(int i = 0; i < m.row; i++)
    77.     {
    78.         for(int j = 0; j < m.col; j++)
    79.             output << setw(3) << m.ptr[i][j];
    80.         output << endl;
    81.     }  
    82.     return output;
    83. }
    84.  
    85. const bool Matrix::operator==(const Matrix &right) const
    86. {
    87.     return (row == right.row && col == right.col) ? 1 : 0;
    88. }
    89.  
    90. const Matrix Matrix::operator+(const Matrix &right)
    91. {
    92.     Matrix temp(row, col);
    93.     for(int i = 0; i < row; i++)
    94.         for(int j = 0; j < col; j++)
    95.             temp.ptr[i][j] = ptr[i][j] + right.ptr[i][j];
    96.     return temp;
    97.     // have problem // return object whose 2D-array is deleted //
    98. }
    99.  
    100. const Matrix &Matrix::operator=(const Matrix &right)
    101. {
    102.     if(this != &right)
    103.     {      
    104.         for(int i = 0; i < row; i++)
    105.             for(int j = 0; j < col; j++)
    106.                 ptr[i][j] = right.ptr[i][j];
    107.     }
    108.     else
    109.         cout << "Self assignment" << endl;
    110.     return *this;
    111. }
    112.  
    113.  
    114. int main()
    115. {
    116.     int row, col;
    117.    
    118.     cout << "Matrix1" << endl;
    119.     cout << "Enter row: ";
    120.     cin >> row;
    121.     cout << "Enter col: ";
    122.     cin >> col;
    123.     Matrix m1(row, col);
    124.     cin >> m1; // Enter elements for matrix1 //
    125.  
    126.    
    127.     cout << "Matrix2" << endl;
    128.     cout << "Enter row: ";
    129.     cin >> row;
    130.     cout << "Enter col: ";
    131.     cin >> col;
    132.     Matrix m2(row, col);
    133.     cin >> m2; // Enter elements for matrix2 //
    134.    
    135.     if(!(m1 == m2)) // compare to do the addition 2 matrices//
    136.     {
    137.         cout << "NO equal";
    138.         cout << endl;
    139.         exit(1);       
    140.     }
    141.    
    142.     Matrix m(row, col); // m is result-matrix //
    143.  
    144.     m = m1 + m2; // Addition error //
    145.     cout << m;
    146.     cout << endl;
    147.     cout << "Finish";
    148.     cout << endl;
    149.  
    150.     return 0;
    151. }
    "what you don't use you don't pay for" (Bjarne Stroustrup).

  2. #2
    Ngày gia nhập
    01 2008
    Nơi ở
    Rất nhiều sóng gió
    Bài viết
    448

    Sai ở trong operator+

    Trích dẫn Nguyên bản được gửi bởi Emerald214 Xem bài viết
    Code:
    Matrix temp(row, col);
    ...
    	return temp;
    	// have problem // return object whose 2D-array is deleted //
    }
    temp được khai báo là biến auto trong operator+ nên nó sẽ bị destruct khi thi hành câu lệnh return. Do lớp Matrix không có copy constructor, temp và return object ở câu lệnh return (vốn dĩ là hai đối tượng khác nhau trong đó return object được copy từ temp) sẽ giống như hai con rắn có cái đầu riêng nhưng có chung 1 cái thân (dùng chung mảng ptr). Khi temp bị destruct mảng ptr của nó bị delete và ptr của return object trở thành con trỏ "mù" (dangling reference) -- nó trỏ vào vùng nhớ đã bị thu hồi.

    Một cách sửa đúng (nhưng không hiệu quả) là bạn viết một copy constructor cho Matrix.
    Đã được chỉnh sửa lần cuối bởi Ada : 04-05-2008 lúc 06:38 PM.

  3. #3
    Ngày gia nhập
    12 2007
    Bài viết
    48

    Hix, em đọc xong mà vẫn "mù" T.T.
    Chị Aida có thể cho em cái code sửa để em tham khảo được ko. Hay cho em 1 ví dụ tương tự cũng dc(cái nào ngắn ngắn, hay hay ấy). Trong sách em cũng dạy copy constructor nhưng em ko hiểu nó để làm chi.
    "what you don't use you don't pay for" (Bjarne Stroustrup).

  4. #4
    Ngày gia nhập
    01 2008
    Nơi ở
    Rất nhiều sóng gió
    Bài viết
    448

    Chỉ cần thêm code này (và khai báo tương ứng trong class):

    Code:
    Matrix::Matrix(const Matrix& a)
    {
    	setMatrix(a.row,a.col);
    	(*this) = a;
    }

    Trong operator+, khi thi hành lệnh return temp, copy constructor Matrix::Matrix(temp) sẽ được gọi để copy (sao chép) giá trị của temp vào return object. Copy constructor này sẽ:

    gọi setMatrix() để lấy đủ bộ nhớ cần thiết cho mảng ptr riêng của return object

    gọi operator=() để thi hành phép gán từng thành phần của giá trị temp vào return object

    Như vậy sau khi thực hiện xong lời gọi Matrix::Matrix(temp) thì return object đã trở thành một đối tượng có cùng giá trị với temp nhưng hoàn toàn độc lập với temp. Nhờ đó việc destruct các biến auto (trong đó có temp) không ảnh hưởng gì đến return object và câu lệnh return hoàn tất.

  5. #5
    Ngày gia nhập
    12 2007
    Bài viết
    48

    Cảm ơn chị đã dành thời gian đọc code của em ^ ^.
    "what you don't use you don't pay for" (Bjarne Stroustrup).

  6. #6
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Mặc định Lỗi bộ nhớ trong lớp xử lý ma trận

    Đây là 1 lỗi rất cơ bản khi class có con trỏ, dùng copy constructor trong các TH sau đây :
    Code:
    There are 3 important places where a copy constructor is called. 
    
    1.When an object is created from another object of the same type 
    2.When an object is passed by value as a parameter to a function 
    3.When an object is returned from a function If a copy constructor is not defined in a class, the compiler itself defines one. This will ensure a shallow copy. If the class does not have pointer variables with dynamically allocated memory, then one need not worry about defining a copy constructor. It can be left to the compiler's discretion.
    
    But if the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor.

  7. #7
    Ngày gia nhập
    12 2007
    Bài viết
    48

    Oh thanks, đọc mấy dòng trên tự nhiên em "sáng" ra hẳn ^ ^
    "what you don't use you don't pay for" (Bjarne Stroustrup).

Các đề tài tương tự

  1. [Hỏi] Cách nhân 2 ma trận với các phần tử của ma trận đợc để trong mảng 1 chiều.
    Gửi bởi code_c trong diễn đàn Nhập môn lập trình C#, ASP.NET
    Trả lời: 4
    Bài viết cuối: 23-09-2012, 10:24 PM
  2. Mảng trên C++ Tính TBC các phần tử của M.Trận B từ các số cho trước trong M.trận A
    Gửi bởi ngoc_le_iu_iu trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 5
    Bài viết cuối: 13-03-2012, 06:22 AM
  3. Làm thế nào để xác định vị trí của ma trận đơn vị trong ma trận a
    Gửi bởi haiictu trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 0
    Bài viết cuối: 10-11-2011, 10:57 AM
  4. Viết hàm con trả về nhiều giá trị trong ma trận?
    Gửi bởi tuan_uct trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 4
    Bài viết cuối: 03-05-2011, 11:11 AM
  5. Biến trả lấy giá trị trả về trong Stored Procedure
    Gửi bởi iamonlining trong diễn đàn Thắc mắc Microsoft SQL Server & Microsoft Access
    Trả lời: 6
    Bài viết cuối: 16-12-2009, 05:24 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn