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

Đề tài: Lỗi: Cấp phát và thu hồi bộ nhớ trong lập trình C++

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

    Arrow Lỗi: Cấp phát và thu hồi bộ nhớ trong lập trình C++

    Cho em hỏi code này em sai gì?
    1) Em nghĩ là sau khi thoát khỏi hàm cấp phát thì nó trở về trạng thái chưa được cấp phát(vì thoát khỏi hàm thì mọi việc đã làm bị xóa sạch), nên khi gọi hàm thu hồi bộ nhớ thì nó delete vùng nhớ không được cấp phát nên bị lỗi. Khi em không dùm hàm thì chạy được(không lẽ cứ phải để tất cả trong hàm main?).

    2) Vậy cho em hỏi bây giờ em muốn cấp phát và thu hồi bộ nhớ thông qua hàm(cho gọn) thì làm sao? (nhiều ngày qua không biết hỏi ai, ngày nào cũng vào cviet mà không được )

    C++ Code:
    1. #include <iostream>
    2. #include <iomanip>
    3. using std::cout;
    4. using std::cin;
    5. using std::endl;
    6.  
    7. void allocation(int **a, const int &row, const int &col);
    8. void deallocation(int **a, const int &row, const int &col);
    9.  
    10. int main()
    11. {  
    12.     int n = 4;
    13.     int **a = 0;
    14.  
    15.     allocation(a, n, n);
    16.     cout << "Allocation success" << endl;  
    17.    
    18.     deallocation(a, n, n);
    19.     cout << "Deallocation success" << endl;
    20.  
    21.     return 0;
    22. }
    23.  
    24. void allocation(int **a, const int &row, const int &col)
    25. {
    26.     a = new int *[row];
    27.     for(int i = 0; i < row; i++)
    28.         a[i] = new int [col];  
    29. }
    30.  
    31. void deallocation(int **a, const int &row, const int &col)
    32. {
    33.     for(int i = 0; i < row; i++)
    34.         delete[] a[i];
    35.     delete[] a;
    36. }
    Đã được chỉnh sửa lần cuối bởi Emerald214 : 04-05-2008 lúc 01:39 PM.
    "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
    447

    Bạn sửa cái này
    Code:
    void allocation(int **a, const int &row, const int &col)
    thành cái này
    Code:
    void allocation(int **&a, int row, int col);
    int **a là chỗ sai phải sửa. int** a là tham số vào (input), còn int**& a là tham số vào ra (input-output). Đối với allocation() thì a phải là tham số ra, nên phải khai báo với int**& a mới được.

    Hai chỗ còn lại không bắt buộc phải sửa nhưng nên sửa. row và col có thể là hằng hoặc biểu thức, thật vô lý khi bắt chúng phải là biến.

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

    Ah, được rồi, cảm ơn chị nhiều lắm, nhưng... **a đã là con trỏ còn thêm &(tham chiếu) nữa là sao vậy chị T.T.
    "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
    447

    Bởi vì allocation() cần phải ghi vào biến a của hàm main(), nên tham số a của allocation() phải là tham số ra. (Do một sự trùng hợp ngẫu nhiên mà cả hai có cùng tên là a, nhưng chắc bạn hiểu "a này" hoàn toàn khác "a kia".)

    Bạn có thể khai báo tham số int **& a hoặc, giống như ở ngôn ngữ C, khai báo int ***a.

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

    Bạn có thể khai báo tham số int **& a hoặc, giống như ở ngôn ngữ C, khai báo int ***a.
    2 cái này là hoàn toàn khác nhau, 1 cái tham chiếu đến con trỏ 1 cái con trỏ đến con trỏ đâu có liên quan gì C và C++ ?
    Bởi vì allocation() cần phải ghi vào biến a của hàm main(), nên tham số a của allocation() phải là tham số ra. (Do một sự trùng hợp ngẫu nhiên mà cả hai có cùng tên là a, nhưng chắc bạn hiểu "a này" hoàn toàn khác "a kia".)
    int **a là chỗ sai phải sửa. int** a là tham số vào (input), còn int**& a là tham số vào ra (input-output). Đối với allocation() thì a phải là tham số ra, nên phải khai báo với int**& a mới được.
    Không hiểu nó có ý nghĩa gì mà cậu lại gọi nó "tham số vào ra" ? Quả thật là đầu tiên tui nghe như vậy nên có hơi thắc mắc.
    Còn theo tui thì :
    - Đơn giản là vì con trỏ cũng là variable, muốn cấp phát cho nó thì cần tham chiếu tới nó vậy thôi. ( dùng & or * cũng vậy chỉ khác ở vấn đề syntax ).
    - Còn giải phóng cho nó, thì vì toán tử new cho 1 global heap memory nên chỉ cần pass ** là đủ.

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

    Mặc định Lỗi: Cấp phát và thu hồi bộ nhớ trong lập trình C++

    Trích dẫn Nguyên bản được gửi bởi rox_rook Xem bài viết
    2 cái này là hoàn toàn khác nhau, 1 cái tham chiếu đến con trỏ 1 cái con trỏ đến con trỏ đâu có liên quan gì C và C++ ?
    Tham chiếu kiểu T và con trỏ trỏ kiểu T có thể nói là rất giống nhau, mình có thể nói về bản chất thì chúng là một, chỉ khác ở cách viết khi khai báo và sử dụng. Nếu giả sử viết trong C thì chỉ có thể dùng con trỏ. Nhưng ở đây viết trong C++ nên có thể dùng cả 2 cách.


    Trích dẫn Nguyên bản được gửi bởi rox_rook Xem bài viết
    Không hiểu nó có ý nghĩa gì mà cậu lại gọi nó "tham số vào ra" ? Quả thật là đầu tiên tui nghe như vậy nên có hơi thắc mắc.
    À đấy là theo hướng chảy của luồng thông tin qua tham số. Tham số cung cấp thông tin cho hàm là tham số "vào". Tham số nhận kết quả thực hiện của hàm là tham số "ra". Ví dụ, tham số a của allocation() là tham số ra. Tham số a của deallocation() là tham số vào.

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

    Nếu giả sử viết trong C thì chỉ có thể dùng con trỏ. Nhưng ở đây viết trong C++ nên có thể dùng cả 2 cách.
    Cậu nói đúng thật, tui dùng gcc nó không cho compile khi truyền tham chiếu tới con trỏ. Nhưng tui vẫn chưa hiểu tại sao C lại không có khái niệm này ? Cậu có article nào liên quan thì cho tui xin tham khảo được không ? Thanks cậu trước.
    Đoạn code này C++ thì ok, gcc thì không được :
    C++ Code:
    1.  
    2. #include <cstdio>
    3. #include <cstdlib>
    4.  
    5. void try_sthing( int**& ref )
    6. {
    7.     **ref = 100;
    8. }
    9.  
    10. int main()
    11. {
    12.     int value = 10;
    13.     int* g1 = &value;
    14.     int** g2 = &g1;
    15.  
    16.     try_sthing( g2 );
    17.     printf("%d ", value);
    18.  
    19.     return 0;
    20. }

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

    Mình không có tài liệu gì lý giải cụ thể về điểm này. Nhưng theo tài liệu lý giải thiết kế chuẩn C99 http://www.open-std.org/JTC1/SC22/WG...onaleV5.10.pdf thì ngôn ngữ C được chuẩn hóa theo 5 nguyên tắc

    - Tin tưởng vào lập trình viên.
    - Không ngăn cản lập trình viên làm việc cần thiết.
    - Giữ cho ngôn ngữ càng nhỏ càng tốt.
    - Chỉ cung cấp đúng một công cụ để làm một việc.
    - Làm cho ngôn ngữ càng nhanh càng tốt, kể cả khi không đảm bảo mã nguồn có thể chuyển đặt được (portable).

    Theo đó việc dùng con trỏ (thay vì tham chiếu, vốn dĩ an toàn hơn nhưng hạn chế hơn) trong C có thể là hệ quả của nguyên tắc thứ 1 và thứ 2. Còn việc không đưa thêm tham chiếu vào chuẩn C99 có thể xem là hệ quả của nguyên tắc thứ 3 và 4.

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

    Mình không có tài liệu gì lý giải cụ thể về điểm này. Nhưng theo tài liệu lý giải thiết kế chuẩn C99 http://www.open-std.org/JTC1/SC22/WG...onaleV5.10.pdf thì ngôn ngữ C được chuẩn hóa theo 5 nguyên tắc

    - Tin tưởng vào lập trình viên.
    - Không ngăn cản lập trình viên làm việc cần thiết.
    - Giữ cho ngôn ngữ càng nhỏ càng tốt.
    - Chỉ cung cấp đúng một công cụ để làm một việc.
    - Làm cho ngôn ngữ càng nhanh càng tốt, kể cả khi không đảm bảo mã nguồn có thể chuyển đặt được (portable).

    Theo đó việc dùng con trỏ (thay vì tham chiếu, vốn dĩ an toàn hơn nhưng hạn chế hơn) trong C có thể là hệ quả của nguyên tắc thứ 1 và thứ 2. Còn việc không đưa thêm tham chiếu vào chuẩn C99 có thể xem là hệ quả của nguyên tắc thứ 3 và 4.
    Thanks . C không có tham chiếu chỉ có con trỏ, sau 1 hồi google thì cũng đã hiểu.
    - Chỉ cung cấp đúng một công cụ để làm một việc.
    Cái này thì quả thật mới biết T_T, thanks cậu Ada rất nhiều

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