Gọi API Lua Đảm Bảo an Toàn Bộ Nhớ - nói dối e blog

Gọi API Lua Đảm Bảo an Toàn Bộ Nhớ

Thiết kế API của Lua được thực hiện một cách tinh tế, toàn bộ thư viện lõi đều ủy thác việc quản lý bộ nhớ cho hàm lua_Alloc do người dùng cung cấp. Bất cứ khi nào xảy ra tình trạng thiếu bộ nhớ, các API của Lua đều có khả năng xử lý ngoại lệ một cách chính xác.

Hãy xem xét các hàm API như lua_newtable hay lua_pushlstring - những hàm này đều yêu cầu tạo ra các đối tượng gc mới. Vậy nếu lua_Alloc không thể cấp phát bộ nhớ trong những trường hợp này thì sao? Đặc biệt các hàm này lại không có giá trị trả về!

Hành vi của Lua lúc này là: ném ra một lỗi bộ nhớ (memory error), nếu không có cơ chế bắt lỗi từ bên ngoài thì hệ thống sẽ kích hoạt hàm panic. Một lỗi phổ biến khi tích hợp Lua vào chương trình chủ thể là:

Nhiều lập trình viên thường tạo máy ảo Lua bằng lua_newstate, sau đó trực tiếp gọi các hàm khởi tạo như luaL_openlibs. Nếu bạn muốn xây dựng hệ thống thật chặt chẽ, cần hiểu rõ rằng quá trình khởi tạo hoàn toàn có thể gặp phải tình trạng không cấp phát được bộ nhớ.

Giải pháp đúng đắn đã được minh họa rõ ràng trong trình thông dịch Lua tự có: Bạn có thể viết một hàm C cho Lua, thực hiện các thao tác cần thiết trên lua_State bên trong hàm này. Sau khi gọi lua_newstate, hãy lập tức sử dụng lua_pcall để kích hoạt hàm C này thay vì gọi trực tiếp. Cách tiếp cận này cho phép tất cả các ngoại lệ bộ nhớ đều được bắt và xử lý thông qua pcall.

Thêm vào đó, phiên bản Lua trước đây từng có hàm lua_cpcall, nhưng kể từ khi Lua hỗ trợ light C function thì API này đã bị loại bỏ.

Việc xây dựng một hệ thống xử lý toàn diện cho các tình huống thiếu bộ nhớ là một công việc đòi hỏi sự cẩn trọng cực độ. Chỉ cần một chi tiết nhỏ bị bỏ sót là toàn bộ nỗ lực sẽ đổ sông đổ bể, đồng thời khiến mã nguồn trở nên phức tạp hơn đáng kể. Vì vậy trong thực tế, phần lớn các dự án của tôi đều từ bỏ việc xử lý vấn đề này, ví dụ như không kiểm tra giá trị trả về của malloc khi không thực sự cần thiết. Lý do là bởi tôi hiểu rõ môi trường vận hành của chương trình - một khi xảy ra thiếu bộ nhớ, hệ thống gần như không thể tiếp tục hoạt động ổn định.

Thay vì làm cho mã nguồn trở nên phức tạp hơn cần thiết mà vẫn có thể bỏ sót các trường hợp đặc biệt, tôi chọn cách đơn giản là giao toàn bộ trách nhiệm xử lý cho hệ điều hành. Nếu tiến trình bị sụp đổ do thiếu bộ nhớ thì đó là điều phải chấp nhận như một phần của quá trình vận hành hệ thống.

0%