Bạn không thể làm con trỏ thông minh trong C vì nó không cung cấp cú pháp cần thiết, nhưng bạn có thể tránh rò rỉ bằng thực hành. Viết mã phát hành tài nguyên ngay sau khi bạn phân bổ nó. Vì vậy, bất cứ khi nào bạn viết malloc
, bạn nên viết free
tương ứng ngay trong phần dọn dẹp.
Trong CI thấy 'GOTO dọn dẹp' mô hình rất nhiều:
int foo()
{
int *resource = malloc(1000);
int retVal = 0;
//...
if (time_to_exit())
{
retVal = 123;
goto cleanup;
}
cleanup:
free(resource);
return retVal;
}
Trong C chúng tôi cũng sử dụng rất nhiều bối cảnh đó phân bổ công cụ, quy tắc tương tự có thể được áp dụng cho điều đó quá:
int initializeStuff(Stuff *stuff)
{
stuff->resource = malloc(sizeof(Resource));
if (!stuff->resource)
{
return -1; ///< Fail.
}
return 0; ///< Success.
}
void cleanupStuff(Stuff *stuff)
{
free(stuff->resource);
}
Điều này tương tự với các nhà xây dựng đối tượng và trình phá hủy. Miễn là bạn không cho đi các nguồn tài nguyên được phân bổ cho các đối tượng khác, nó sẽ không bị rò rỉ và con trỏ sẽ không lơ lửng.
Không khó để viết trình phân bổ tùy chỉnh theo dõi phân bổ và viết các khối bị rò rỉ atexit
.
Nếu bạn cần đưa con trỏ đến tài nguyên được phân bổ, bạn có thể tạo ngữ cảnh bao bọc cho nó và mỗi đối tượng sở hữu ngữ cảnh trình bao thay vì tài nguyên. Những trình bao bọc này chia sẻ tài nguyên và một đối tượng truy cập, theo dõi việc sử dụng và giải phóng các đối tượng khi không ai sử dụng nó. Đây là cách hoạt động của các công cụ shared_ptr
và weak_ptr
của C++ 11. Nó được viết chi tiết hơn ở đây: How does weak_ptr work?
Làm thế nào nó hoạt động? Làm thế nào nó có thể theo dõi các phép gán con trỏ? – Calmarius
@Calmarius Có nhiều cách khác nhau mà chúng hoạt động. Xem: http://en.wikipedia.org/wiki/Garbage_collection_(computer_science) –
Tôi hiểu. Tôi hỏi về GC bạn đã liên kết. Nó tuyên bố nó hoạt động trên các chương trình C chưa sửa đổi, bằng cách thay thế chỉ malloc và realloc. Nhưng làm thế nào nó xác định vị trí các con trỏ trỏ đến khối được phân bổ? Chúng có thể được sao chép xung quanh trong chương trình. – Calmarius