2009-03-05 59 views
8

Dùng ứng dụng Windows chuẩn. Nó tải một DLL bằng cách sử dụng LoadLibrary để gọi một hàm trong nó (chúng ta sẽ gọi hàm DLL_A) này. Hàm đó nạp một DLL khác (chúng ta sẽ gọi nó là DLL_B). Các ứng dụng hiện nay dỡ DLL_A DLL bằng cách sử dụng FreeLibrary vì nó không còn đòi hỏi nó.Liệu một DLL có được loại bỏ nếu DLL nạp nó được dỡ xuống không?

Câu hỏi đặt ra là: DLL_B có còn trong bộ nhớ và được tải không?

Đây có phải là điều tôi có thể phụ thuộc hay không có giấy tờ?

Trả lời

10

No. DLL_B sẽ không được tải. Cuộc gọi LoadLibrary() được thực hiện bởi DLL_A sẽ tăng số lượng tải cho DLL_B. Vì không có cuộc gọi FreeLibrary() tương ứng với số DLL_B, số lần truy cập sẽ không chuyển thành số không.

Từ LoadLibrary() tài liệu:

Hệ thống duy trì một tính tham khảo cho mỗi quá trình trên tất cả các module được nạp. Gọi hàm LoadLibrary tăng số lượng tham chiếu . Gọi số FreeLibrary hoặc Hàm FreeLibraryAndExitThread sẽ giảm số lượng tham chiếu. Hệ thống dỡ một mô-đun khi số tham chiếu của nó đạt đến 0 hoặc khi quá trình chấm dứt (bất kể số lượng tham chiếu ).

+0

Và chà là bạn không phải gọi FreeLibrary() trong DLLMain trên một quá trình tách, vậy làm thế nào bạn sẽ thực sự đi về làm sạch lên DLL_B? –

+0

Một phương pháp phổ biến là có các lệnh gọi init() và deinit() cho DLL_A tải/dỡ DLL_B (và thực hiện các hàm init/cleanup khác). Nó xâm nhập, nhưng nó đơn giản. –

+0

Trong trường hợp này, tôi muốn * DLL_B bị bỏ lại phía sau cho đến khi ứng dụng chính đóng. Thật vậy, điều này là lý tưởng cho tôi. Ý định của tôi là tiêm DLL và một chuỗi nó sẽ tạo ra trong ứng dụng. – mj2008

1

Đọc phần Ghi chú để biết giải thích chi tiết.

Điều quan trọng cần lưu ý là: hệ thống

duy trì một số tài liệu tham khảo cho mỗi quá trình cho mỗi mô-đun nạp

và tiếp tục xuống

Khi tính tham khảo của một mô-đun đạt đến số không hoặc quá trình chấm dứt, hệ thống sẽ tải mô-đun từ không gian địa chỉ của quá trình

Từ MSDN:

Giải phóng các tải dll (DLL) mô-đun và, nếu cần thiết, decrements đếm tham chiếu của nó. Khi số tham chiếu đến bằng không, mô-đun được tải xuống từ không gian địa chỉ của quá trình gọi và xử lý không còn giá trị.

1

Dll trong cửa sổ được tính tham chiếu. Khi A được unloaded bạn đang giảm số lượng tham chiếu trên A, nếu nó chạm 0 thì nó sẽ không tải, và (giả định không có lỗi trong mã) giảm số lượng tham chiếu trên B. Nếu số lần truy cập trên B tiến đến 0 thì nó sẽ được dỡ . Có thể DLL C có số lần trả về B, và dỡ A sẽ không dỡ B

3

Bạn sẽ có một xử lý rò rỉ trong trường hợp:

Program -Load> Dll A 
      -Load> Dll B 
     -Unload> Dll A 

Không có mã đang ngầm thực hiện bởi một mô-đun được bốc dỡ dỡ bỏ các module mà nó nạp.

Vì không có mã nào được thực hiện để giảm số lượng tham chiếu, mô-đun B sẽ không bao giờ được tải xuống.

Dưới đây là các quy tắc cho tải/dlls dỡ:

  • Mỗi cuộc gọi đến LoadLibrary và LoadLibraryEx sẽ làm tăng số lần tham khảo cho mô-đun đó. Đây là trong bối cảnh của quá trình gọi điện thoại chỉ, không qua ranh giới quá trình.
  • Mỗi cuộc gọi tới FreeLibrary hoặc FreeLibraryAndExitThread sẽ giảm số lượng tham chiếu.
  • Khi số tham chiếu đạt đến 0, số này sẽ không được tải.
  • Khi Windows thấy rằng chương trình của bạn là đóng, bất kỳ mô-đun chưa tải nào bị rò rỉ sẽ được tải xuống.
  • Tùy thuộc vào việc bạn đang làm, DllCanUnloadNow có thể hữu ích cho bạn.

Vẫn trong bộ nhớ vs vẫn nạp:

Không có đảm bảo rằng mô-đun của bạn sẽ được phát hành từ bộ nhớ tại một thời điểm nhất định khi tham chiếu đến 0. Nhưng bạn nên xem xét các mô-đun như thể nó được bốc dỡ khi đếm tham khảo đạt 0.

Dừng các DLL khỏi bị bốc dỡ:

Để buộc các DLL khỏi bị bốc dỡ bạn có thể thử

  • Hệ thống gọi DllMain với cờ DLL_PROCESS_DETACH. Bạn có thể cố gắng không quay trở lại từ điều này thông qua một số loại hoạt động chặn.
  • Bạn có thể thử gọi LoadLibrary từ bên trong DLL mà bạn không muốn tải xuống. (Tự tải)

Edit:

Bạn nói mục tiêu của bạn là để injet mã vào chương trình đang chạy và bạn muốn rò rỉ tay cầm vào mục đích.

Điều đó là tốt, nhưng nếu bạn chạy thao tác này rất nhiều, nó có thể dẫn đến sự cố trong Chương trình nguồn của bạn vì quá nhiều tay cầm sẽ được sử dụng hoặc cuối cùng quá nhiều bộ nhớ sẽ được sử dụng.

Bạn có thể trả về FALSE từ DllMain để ngăn không cho nó bị tải để bạn không lãng phí bộ nhớ. Bạn làm điều này khi fdwReason là DLL_PROCESS_ATTACH. Bạn có thể read more about it here.

Nếu bạn đang cố gắng mô phỏng một DLL và thêm vào chức năng bổ sung của riêng bạn, bạn sẽ cần phải thực hiện tất cả các chức năng mà DLL nguồn thực hiện và ủy nhiệm mỗi cuộc gọi trở lại nguồn DLL.

+0

Tôi khá vui khi bị rò rỉ xử lý vì DLL_B thực sự sẽ thực hiện một chức năng hữu ích. Tôi muốn "tiêm" nó vào ứng dụng. – mj2008

+0

Đã cập nhật phản hồi của tôi để bao gồm điều này. –

+0

TVM - vấn đề đa tải là điều tôi sẽ suy ngẫm. – mj2008

Các vấn đề liên quan