- vừa được xem lúc

C/C++: SMART POINTER

0 0 4

Người đăng: Toàn Vũ Đức

Theo Viblo Asia

1. Một số vấn đề với con trỏ thông thường trong C/C++

a. Memory Leaks:

Điều này xảy ra khi bộ nhớ được cấp phát nhiều lần bỏi một chương trình nhưng không bao giờ được giải phóng. Điều này dẫn đến việc tiêu thụ bộ nhớ quá mức cuối cùng dẫn đến sự cố hệ thống VD:

#include <iostream>
using namespace std; class Rectangle {
private: int length; int breadth;
}; void fun() { Rectangle* p = new Rectangle();
} int main() { while(1) { fun(); //ham fun tao 1 con tro Rectangle }
}

b. Dangling Pointer:

Là con trỏ trỏ đến dữ liệu không hợp lệ hoặc dữ liệu không hợp lệ nữa (dữ liệu đã từng hợp lệ) VD:

Class *object = new Class();
Class *object2 = object; delete object;
object = nullptr;
//Dễ thấy sau khi giải phóng cho obj thì obj2 bây h sẽ trỏ đến thứ gì đó không còn hợp lệ nữa

Điều này có thể xảy ra ngay cả đối với các đối tượng trong vùng nhớ Stack (Memory Layout):

Object *method() { Object object; return &object;
} Object *object2 = method();
//Có thể thấy obj2 chính là 1 dangling pointer vì obj2 trỏ đến obj nhưng khi kết thúc hàm thì nó sẽ bị xóa khỏi Stack

c. Wild Pointer:

Con trỏ chưa được khởi tạo được gọi là con trỏ hoang dã vì chúng trỏ đến một số vị trí bộ nhớ tùy ý và có thể khiến chương trình bị lỗi hoặc hoạt động không mong muốn VD:

// C program that demonstrated wild pointers
int main()
{ /* wild pointer */ int* p; /* Some unknown memory location is being corrupted. This should never be done. */ *p = 12;
}

d. Data Inconsistency:

Dữ liệu khộng nhất quán xảy ra khi một số dữ liệu được lưu trữ trong bộ nhớ nhưng không được cập nhật một cách nhất quán

e. Buffer Overflow

Tràn bộ đệm được sử dụng để ghi dữ liệu vào một địa chỉ bộ nhớ nằm ngoài khối bộ nhớ được cấp phát. Điều này dẫn đến việc dữ liệu bị hỏng có thể bị khai thác bỏi những kẻ tấn công nguy hiểm

2. SMART POINTER

  • Con trỏ thông minh là 1 trình bao bọc trên một con trỏ có toán tử như * và ->
  • Các đối tượng của con trỏ thông minh trông giống như con trỏ bình thường, và nó có thể tự giải phóng và giải phóng bộ nhớ của đối tượng bị hủy

a. Các loại Smart Pointer

  • auto_ptr
  • unique_ptr
  • shared_ptr
  • weak_ptr

Cách tạo 1 Smart Pointer mà không cần thư viện mẫu

#include <iostream>
using namespace std;
class SmartPtr { int *ptr;
public: explicit SmartPtr(int * p = NULL) {ptr = p;} //yêu cầu dùng hàm khởi tọa này //Destructor ~SmartPtr() {delete (ptr);} //Overloading dereferencing operator int& operator*() {return *ptr;}
}; int main()
{ SmartPtr ptr(new int()); //SmartPtr ptr; *ptr = 20; cout << *ptr; return 0;
}

Cách tạo 1 Smart Pointer cho mọi đối tượng (Dùng Template)

#include <iostream>
using namespace std; class Person {
public: void display() { cout << "Hello, I'm a person!" << endl; }
}; template <class T> class SmartPointer{ T* ptr;
public: SmartPointer(T* p = NULL) {ptr = p;} ~SmartPointer() {delete ptr;}; T& operator*() {return (*ptr);} T* operator->() {return ptr;}
}; int main() { SmartPointer<int> ptr(new int()); *ptr = 20; cout << *ptr << endl; SmartPointer<Person> p (new Person()); p->display(); return 0;
}

b. Unique_Pointer

  • Chỉ lưu trữ 1 con trỏ
  • Chúng ta có thể gán một đối tượng khác bằng cách xóa đối tượng hiện tại khỏi con trỏ
#include <iostream>
#include <memory>
using namespace std; class Rectangle { int length; int breadth;
public: Rectangle(int l, int b) { length = l; breadth = b; } int area() {return length * breadth;}
}; int main() { unique_ptr<Rectangle> P1(new Rectangle(10,5)); cout << P1->area() << endl; //unique_ptr<Rectangle> P2(P1); unique_ptr<Rectangle> P2; P2 = move(P1); cout << P2->area() << endl; return 0;
}

c. Shared Pointer

  • Bằng cách sử dụng shared pointer nhiều con trỏ có thể trỏ đến một đối tượng tại một thời điểm
  • Nó duy trì bộ đém tham chiếu bằng phương thức use_count().
#include <iostream>
#include <memory>
using namespace std; class Rectangle { int length; int breadth;
public: Rectangle(int l, int b) { length = l; breadth = b; } int area() { return length * breadth;}
}; int main() { shared_ptr<Rectangle> P1(new Rectangle(10,5)); cout << P1 -> area() << endl; shared_ptr<Rectangle> P2; P2 = P1; shared_ptr<Rectangle> P3; P3 = P1; cout << P2 -> area() << endl; cout << P1 -> area() << endl; cout << P1.use_count() << endl; cout << P2.use_count() << endl;
}

Trường hợp Memory Leak

#include <iostream>
#include <memory>
using namespace std; class Person {
public: std::shared_ptr<Person> friendPtr; std::string name; Person(const std::string& n) : name(n) { cout << "Created! Use count: " << friendPtr.use_count() << std::endl; } ~Person() { cout << name << "destroyed!" << endl; }
}; int main() { shared_ptr<Person> person1(new Person("Toan")); shared_ptr<Person> person2(new Person("Quynh")); person1->friendPtr = person2; person2->friendPtr = person1; cout << "After creating objects: " << endl; cout << "Alice use count:" << person1.use_count() << endl; cout << "Bob use count:" << person2.use_count() << endl; std::cout << "Address of Alice's friend: " << person1->friendPtr.get() << std::endl; std::cout << "Address of Bob's friend: " << person2->friendPtr.get() << std::endl; return 0;
}

d. Weak_Pointer (Update sau)

Bình luận

Bài viết tương tự

- vừa được xem lúc

Memory layout của một chương trình C/C++

1. Đặt Vấn Đề.

0 0 35

- vừa được xem lúc

Sự khác nhau giữa bộ nhớ Heap và bộ nhớ Stack trong lập trình

1. Giới thiệu. . Như chúng ta đã biết thì việc Quản lý bộ nhớ đối với một lập trình viên là rất quan trọng.

0 0 47

- vừa được xem lúc

Tích hợp thư viện C/C++ vào một dự án Flutter như thế nào?

Chào các bạn hôm nay rảnh rỗi thì mình viết một bài hướng dẫn về cách tích hợp một thư viện C/C++ vào một dự án Flutter. Thì cũng khá đơn giãn thôi vì Flutter đã cũng cấp cho chúng ta một thư viện khá

0 0 50

- vừa được xem lúc

Programming

Definition of Programming. .

0 0 20

- vừa được xem lúc

Gọi hàm của C++ trong Python bằng ctypes

Nếu đã từng dùng qua các thư viện liên quan đến toán học của Python như numpy, các bạn sẽ để ý thấy các nó có tốc độ xử lý rất nhanh. Điều này là do một phần của package này được viết bằng C/C++ và ph

0 0 28

- vừa được xem lúc

Build ứng dụng Cross Platform với Go và CGO

1. Giới thiệu.

0 0 22