Bỏ qua để đến nội dung

Con trỏ treo (Dangling Pointer)

Một con trỏ treo (dangling pointer) là con trỏ vẫn giữ địa chỉ của một vùng nhớ đã bị giải phóng hoặc không còn hợp lệ. Dùng nó tiếp tục là hành vi không xác định (undefined behavior).

int* ptr = new int(42);
delete ptr;
std::cout << *ptr << std::endl; // NGUY HIỂM! ptr đang "treo" - vùng nhớ đã bị giải phóng

Trường hợp 2: trả về con trỏ đến biến cục bộ

Phần tiêu đề “Trường hợp 2: trả về con trỏ đến biến cục bộ”
int* create_number() {
int local_value = 42;
return &local_value; // NGUY HIỂM! local_value bị hủy khi hàm kết thúc
}
int main() {
int* ptr = create_number();
std::cout << *ptr << std::endl; // Undefined behavior - biến gốc không còn tồn tại
return 0;
}

Vùng nhớ mà con trỏ treo trỏ đến có thể:

  • Vẫn còn dữ liệu cũ (chương trình “vô tình chạy đúng” một cách may mắn)
  • Đã bị hệ thống cấp phát cho mục đích khác - đọc/ghi vào đó có thể làm hỏng dữ liệu không liên quan
  • Gây crash ngay lập tức (nếu vùng nhớ đã được trả lại hệ điều hành)

Tính chất “có thể chạy đúng một cách ngẫu nhiên” khiến lỗi này đặc biệt khó phát hiện khi test.

int* ptr = new int(42);
delete ptr;
ptr = nullptr; // Luôn gán nullptr ngay sau khi delete
if (ptr != nullptr) { // Kiểm tra trước khi dùng
std::cout << *ptr << std::endl;
}

Với trường hợp trả về con trỏ đến biến cục bộ, giải pháp là dùng cấp phát động (nếu thực sự cần con trỏ sống lâu hơn hàm) hoặc trả về theo giá trị:

int create_number() { // Trả về theo GIÁ TRỊ, không phải con trỏ
int local_value = 42;
return local_value; // An toàn - trả về một bản sao
}

Con trỏ treo: con trỏ trỏ đến vùng nhớ đã bị giải phóng hoặc không còn hợp lệ.

  • Luôn gán nullptr sau khi delete
  • Không bao giờ trả về địa chỉ của biến cục bộ (biến trên stack)
  • Ưu tiên smart pointer để tránh loại lỗi này gần như hoàn toàn