-
07-10-2008, 01:03 PM #1Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
SmartPointer trong lập trình VC++?
Lạy hồn!.
Đông vãi chưởng, hix, muốn vào post cái bài cũng khó khăn, mạng rớt lên rớt xuống thế này[IMG]images/smilies/Cry.gif[/IMG] .
À, spam tý, đang bức xúc [IMG]images/smilies/dont_know.gif[/IMG] .
Ai đã từng dùng C++ để làm một cái gì đó trên mức nhỏ một tý chắc hẳn đều vấp phải cái vấn đề củ chuối muôn thủa. "Memory Leak".
Trích lời cụ bull.
Cần hiểu là diệt memory leak chỉ để tránh thiếu memory khi ct đang chạy(vì ko chịu free) + tránh tốn memory cho mấy ct khác thôi, chứ có malloc mà ko free thì ở cuối ct thì OS như Windows,Mac hay Linux nó đều free hộ. Chỉ có DOS lởm là ko làm đc như thế thôi.
Biết mỗi 2 kiểu chính.
-Reference counting: Mỗi object có một cái counter. Nó đếm số thằng đang sử dụng object đó. Counter của object đó về 0 là ko ai thèm nó nữa -> xóa.
Việc ref countering này thường được làm bởi smart pointer(Tham khảo boost, SGF cũng đc). Hoặc làm = tay(irrlicht, COM) .
Ưu điểm: -Nhanh, gọn nhẹ
Nhược điểm: Clyclic reference. Object A có cái pointer vào object B. Object B lại có pointer vào Object A. Dễ thấy là 2 thằng này nó ôm nhau, cả 2 thằng sẽ ko bao giờ bị xóa vì chúng nó đều có ref counter=1 -> leak
Khắc phục: Weak pointer, một cái pointer mà ko tăng reference. Tự reset về null khi object bị delete
Tham khảo : Boost
-Garbage collection. Đại loại là có một cái object gọi là garbage collector, nó sẽ scan và tìm xem object nào ko ai point đến mà ko dựa vào reference counting. Tớ biết mỗi kiểu mark-and-sweep:
-Có một cái gọi là root.
-Mọi object tạo ra đều đc lưu vào array
-Mọi object ở mức global đều nối trực tiếp vào root
-Mỗi object có thể có pointer đến các object khác, các object con của nó, các object con lại nối vào parent object
--> Có một cái dạng như cái cây
Increment GC thì chịu.
Khi lượng memory sử dụng đã lớn, việc collect garbage bắt đầu.
Chạy từ gốc(root) đến ngọn, và đánh dấu các object có đc reference, các object con của các object đc reference
Quét qua cả cái array, tìm những thằng ko đánh dấu và diệt
Bỏ đánh dấu toàn bộ các object
Dễ thấy là cách này dẹp đc cyclic reference vì nếu A point vào B và B point vào A trong khi ko có ai khác point vào A lẫn B thì sẽ như hình sau:
Mã:Root - ob2 - obj6 \ ob1 \ ob3 / \ ob4 ob5 A-B
Ưu điểm: Đơn giản giải quyết đc cyclic reference
Nhược điểm:
-Overhead nhiều hơn, nhất là khi đang scan
-Trong các implementation của C++, syntax của chúng nó khá xấu
-Template phức tạp hơn Smart pointer vì cần có 2 loại pointer khác nhau: Global/scope pointer và member pointer để tạo ra cấu trúc tree như trên
-Ko thể tạo mấy object mà có sử dụng garbage collector trên stack
Khắc phục:
-Cố mà chịu, đây là C++
-Sử dụng Managed C++ (Windows only, nhưng mà nếu ko ngại bắt người dùng cài .NET thì ko phải vấn đề lớn), syntax đẹp hơn nhiều
Nó đây.
Mã:#ifndef _SGF_PTR_H_#define _SGF_PTR_H_ /// \brief A smart pointer for sgfObject/// \see sgfObjecttemplate<class T>class sgfPtr{public: sgfPtr():ptr(0) { } sgfPtr(const T* obj) :ptr(0) { assign(obj); } sgfPtr(const sgfPtr<T>& obj) :ptr(0) { assign(obj.ptr); } ~sgfPtr() { if(ptr) ptr->decRef(); } sgfPtr& operator=(T* obj) { assign(obj); return *this; } sgfPtr& operator=(const sgfPtr<T>& obj) { assign(obj.ptr); return *this; } inline friend bool operator==(const T* other, const sgfPtr<T>& me) { return(me.ptr==other); } inline friend bool operator==(const sgfPtr<T>& me, const sgfPtr<T>& other) { return(me.ptr==other.ptr); } inline friend bool operator!=(const T* other, const sgfPtr<T>& me) { return(me.ptr!=other); } inline friend bool operator!=(const sgfPtr<T>& me, const sgfPtr<T>& other) { return(me.ptr!=other.ptr); } /// \brief Return the real pointer /// emarks This should only be used for null checking T* getPtr() const { return ptr; } T* operator->() const { return ptr; } T& operator*() const { return *ptr; } operator T* () const { return ptr; } ///\brief Perform static_cast on the object template<class T2> T2* staticCast() const { return static_cast<T2>(this); } /// \brief Perform dynamic_cast on the object template<class T2> T2* dynamicCast() const { return dynamic_cast<T2>(this); } private: void assign(const T* obj) { T* o=const_cast<T*>(obj); if(o) o->addRef(); if(ptr) ptr->decRef(); ptr=o; } T* ptr;}; #endif
Mã:class sgfObject{public: sgfObject():refCounter(0) { }protected: virtual ~sgfObject() { }public: /// \brief add reference void addRef() { ++refCounter; } /// \brief remove reference /// and delete the object if reference ==0 void decRef() { --refCounter; if(!refCounter) { delete this; } } private: int refCounter;};
Mã:class Test;public: TestClass() { cout << "Hahaha! ta day "; } virtual ~TestClass() { cout << "Chet toi roi "; }}; class Class1; class Class2{private: TestClass* ptr;public: Class2(TestClass* ptr, Class1* sender) { this->ptr = ptr; cout << "Class 2 da duoc tao "; }public: ~Class2() { cout << "Class 2 da ngom "; }}; class Class1{private: TestClass* ptr;public: Class1() { cout << "Class 1 da duoc tao "; ptr = new TestClass(); Class2* c2ptr = new Class2(ptr, this); if(c2ptr) delete c2ptr; }public: ~Class1() { cout << "Class 1 da ngom "; }}; int main(){ Class1* ptr = new Class1(); if(ptr) delete ptr; cin.get(); return 0;}
Đừng thắc mắc tại sao lại lằng nhằng thế [IMG]images/smilies/waiting.gif[/IMG] , NVD mới chỉ mô phỏng lại một tình huống siêu đơn giản. So với một cái project thật sự với hàng chục người cùng tham gia, hàng trăm con trỏ(thậm chí hàng ngìn [IMG]images/smilies/21.gif[/IMG] ) và một mớ object ôm lẫn nhau thì thế là còn ít chán![IMG]images/smilies/Cry.gif[/IMG] .
Kết quả.
Class1 da duoc tao
Hahaha! ta day
Class2 da duoc tao
Class2 da ngom
Class1 da ngom
Sửa lại đoạn code trên.
Mã:class Class2{private: sgfPtr<TestClass> ptr;// <-----------------------Chú ýpublic: Class2(TestClass* ptr, Class1* sender) { this->ptr = ptr; cout << "Class 2 da duoc tao "; }public: ~Class2() { cout << "Class 2 da ngom "; }}; class Class1{private: sgfPtr<TestClass> ptr;// <-----------------------Chú ýpublic: Class1() { cout << "Class 1 da duoc tao "; ptr = new TestClass(); Class2* c2ptr = new Class2(ptr, this); if(c2ptr) delete c2ptr; }public: ~Class1() { cout << "Class 1 da ngom "; }};
Class1 da duoc tao
Hahaha! ta day
Class2 da duoc tao
Class2 da ngom
Class1 da ngom
Chet toi roi
Bạn có thể nói rằng:
-ok, nhưng nếu tôi chỉ thêm một phát cái "delete TestClass;" vào destructor của class Class1 thì sao?.
Ai jà, nge hấp dẫn quá nhỉ. Nhưng đừng vội mừng với sáng kiến của mình, giả dụ, vì một lý do gì đó. Mà Class2 truyền con trỏ "TestClass" lại cho một class3 hay 4 gì khác. Thế rồi ta delete cái Class1 đi -> cái TestClass cũng đi theo. Lúc đó thì sao?. Rõ ràng vẫn còn đối tượng muốn sử dụng cái TestClass. Mà tiếc thay cái TestClass đã ra người thiên cổ->lỗi ngoài ý muốn [IMG]images/smilies/Cry.gif[/IMG] .
Sử dụng smartpointer sẽ đảm bảo được việc delete đối tượng được cấp phát động đúng lúc. Không quá sớm mà cũng không quá muộn(sớm thì lỗi, muộn thì leak). Khi ta vẫn còn cần, nó vẫn còn phải sống. Khi chắc chắn ta không cần nữa nó nữa, nó tự xử [IMG]images/smilies/wave.gif[/IMG] .View more random threads:
- Một số kĩ thuật cơ bản với Irrlicht
- Kỹ thuật Sprite Xóa Ảnh Thừa Trong Game
- Screen Reader Visual C++ | Đọc nội dung trên màn hình viết bằng VC++
- Ưu điểm Lập Trình Multi - core
- Hỏi về: Làm sao để xóa đề tài này hoặc di chuyển sang mục khác
- Tìm hiểu về âm thanh và âm nhạc trong lập trình C ( Win32API)
- Ghi dữ liệu lên file trong Lập trình VC++
- Memory tracker
- Using __cpuid to get CPU information!!!
- Ở Đâu Sửa Laptop Tại Chỗ Q 5 Chất Lượng
-
07-10-2008, 01:33 PM #2Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Cám ơn bạn NamVoDang ! Bài viết rất có giá trị. Mình cũng đang cần.
-
07-10-2008, 01:39 PM #3Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Hừm, đọc lại vẫn chưa rõ ràng gì cả . Thôi làm phát nữa.
Cáh khai báo smartpointer.
Mã:sgfPtr<TestClass> ptr;
-> Counter lại giảm đi một. Mà khi Counter về 0 có ngĩa là chả ma nào thèm nữa -> cái object tự sát.
Thanh lý pallet nhựa cũ Đaklak Trải dài trên vùng đất Daklak, những chiếc pallet nhựa cũ Đaklak nằm rải rác như những bức tranh tĩnh lặng, kể lể về những chặng đường mà chúng đã đi qua. Những đường...
Thanh lý pallet nhựa cũ Đaklak