Xử Lý Lỗi LoadLibrary Không Thể Tải Được DLL
Hôm nay, một đồng đội của chúng ta đang gặp rắc rối khi đóng gói thư viện Open Asset Import Library thành thư viện Lua. Vấn đề kỳ lạ là phiên bản biên dịch trong môi trường Visual Studio lại chạy ngon lành, nhưng khi chuyển sang dùng MinGW-GCC thì lập tức báo lỗi “Không tìm thấy module được chỉ định” hoặc “Không tìm thấy chương trình được chỉ định”.
Phải nói thật lòng là Microsoft đúng là “đủ đô” khi đầu tư cả đội ngũ hùng hậu để quốc tế hóa toàn bộ thông báo lỗi. Điều này khiến chúng ta - các lập trình viên Trung Quốc (và nhiều quốc gia khác) - cực kỳ khó khăn khi tìm kiếm giải pháp trên Google. Nếu bạn từng thử dùng lệnh export LANG=C
để chuyển locale sang chế độ tiếng Anh mà vẫn không thể khiến chuỗi lỗi từ GetLastError
qua FormatMessage
hiển thị bằng tiếng Anh trên Windows thì hẳn sẽ đồng cảm. Rất mong các chuyên gia Windows đang đọc bài này chia sẻ kinh nghiệm trong phần bình luận. Mục đích chính của bài viết này cũng là để tạo một tài liệu tham khảo bằng tiếng Anh - nhằm giúp các lập trình viên tương lai dễ dàng tìm thấy giải pháp khi gặp lỗi tương tự.
Dù không hiểu rõ cơ chế nội tại Windows nhưng theo kinh nghiệm, khi gặp các lỗi kiểu “module không tồn tại” hay “chương trình mất tích”, nguyên nhân thường liên quan đến sự thiếu hụt DLL phụ thuộc. Công cụ Dependency Walker chính là trợ thủ đắc lực trong trường hợp này. Ban đầu được tích hợp sẵn trong Visual C++, giờ đây bạn có thể tải phiên bản độc lập về sử dụng. Nếu đã cài MinGW/MSYS, mình khuyên bạn dùng ldd
(có sẵn trên Linux nhưng hiện đã hỗ trợ Windows). Đây là công cụ cực mạnh để kiểm tra mối quan hệ phụ thuộc DLL.
Trường hợp tương tự đã từng xảy ra trong dự án iupmingw của mình, bạn có thể xem chi tiết tại: . Tuy nhiên, lần này không phải do thiếu DLL. Điều khó chịu là Windows không hề chỉ rõ giai đoạn nào xảy ra lỗi - không thông báo tên file DLL bị thiếu. Mình đã phải nhờ đến “bảo bối” ProcessMonitor - công cụ kinh điển để theo dõi các syscall của tiến trình như: tải DLL, mở file, truy cập registry… Nhờ đó, lập trình trên Windows sẽ không còn bị “mù mờ”. Bạn còn có thể dùng nó để kiểm tra tại sao một file nào đó không xóa được - thường là do bị khóa bởi tiến trình khác.
Về lỗi “Không tìm thấy module được chỉ định” (Error Code 126 - The specified module could not be found), đây là dấu hiệu rõ ràng cho thấy một DLL phụ thuộc đang “biến mất không lời cáo biệt”. Còn lỗi “Không tìm thấy chương trình được chỉ định” (Error Code 127 - The specified procedure could not be found) lại chỉ ra vấn đề nghiêm trọng hơn: DLL vật lý vẫn tồn tại, nhưng các ký hiệu (symbol) bên trong không khớp - thường do xung đột phiên bản.
Trong trường hợp cụ thể này, nguyên nhân gốc rễ có thể bắt nguồn từ việc trộn lẫn cơ chế xử lý ngoại lệ sjlj và seh khi biên dịch bằng MinGW GCC C++. Đây là một chủ đề thú vị khác mà mình sẽ chia sẻ chi tiết trong bài viết tới.
Mẹo nhỏ: Khi làm việc với DLL, đừng quên kiểm tra kỹ biến môi trường PATH
và đảm bảo các thư viện phụ thuộc được đặt trong các thư mục có quyền truy cập phù hợp. Nếu đang dùng MinGW, hãy thử chạy lệnh mingw-get install mingw32-libz
để cập nhật các thư viện hệ thống cần thiết.