2012-12-26 30 views
6

Từ tài liệu MSDN, chúng ta có thể thấy rằng, chúng ta không nên gọi LoadLibrary/FreeLibrary trong chức năng điểm nhập DllMain.Chúng ta có thể gọi FreeLibrary từ ExitInstance

Chức năng điểm nhập chỉ nên thực hiện khởi tạo đơn giản hoặc tác vụ chấm dứt. Nó không được gọi hàm LoadLibrary hoặc LoadLibraryEx (hoặc một hàm gọi các hàm này), bởi vì điều này có thể tạo các vòng phụ thuộc trong thứ tự tải DLL. Điều này có thể dẫn đến một DLL đang được sử dụng trước khi hệ thống đã thực thi mã khởi tạo của nó. Tương tự, chức năng nhập điểm không được gọi hàm FreeLibrary (hoặc chức năng gọi FreeLibrary) trong quá trình chấm dứt , vì điều này có thể dẫn đến DLL được sử dụng sau khi hệ thống đã thực thi mã kết thúc.

Câu hỏi của tôi là: Chúng tôi có thể gọi FreeLibrary từ ExitInstance() không? ví dụ:

test.exe - thực thi chính

HINSTANCE hDllMFC = LoadLibrary(L"TestApp.dll"); 
if (hDllMFC != NULL) 
{ 
    FreeLibrary(hDllMFC); 
} 

while unload the hDllMFC, the call stack looks like: 

TestApp.dll!CTestAppApp::ExitInstance() Line 42 C++ 
TestApp.dll!InternalDllMain() Line 155 C++ 
TestApp.dll!DllMain() Line 272 C++ 
TestApp.dll!__DllMainCRTStartup() Line 512 C 
TestApp.dll!_DllMainCRTStartup() Line 477 C 
ntdll.dll!LdrpUnloadDll() Unknown 
ntdll.dll!LdrUnloadDll() Unknown 
KernelBase.dll!FreeLibrary() Unknown 
Test.exe!wmain() Line 17 C++ 

TestApp.dll - DLL thường xuyên động liên quan đến MFC

CTestApp theApp; 
HINSTANCE hDllResource = NULL; 

BOOL CTestApp::InitInstance() 
{ 
    hDllResource = ::LoadLibrary(L"TestApp_Resource.dll"); 

    return CWinApp::InitInstance(); 
} 

int CTestApp::ExitInstance() 
{ 
    ::FreeLibrary(hDllResource); 

    return CWinApp::ExitInstance(); 
} 

TestApp_Resource.dll - DLL thường xuyên , tài nguyên

...

Tôi nghĩ rằng chúng ta không nên, nhưng từ việc implation của CWinApp :: ExitInstance(), chúng ta có thể thấy rằng, nó cũng đã cố gắng để dỡ bỏ dll tài nguyên. Điều đó có nghĩa là chúng ta có thể gọi FreeLibrary trong ExitIntance()?

int CWinApp::ExitInstance() 
{ 
    //... 

if (m_hLangResourceDLL != NULL) 
    { 
    ::FreeLibrary(m_hLangResourceDLL); 
    m_hLangResourceDLL = NULL; 
    } 
    //... 
} 

Tôi cũng tìm thấy tài liệu xác nhận có lỗi khi gọi FreeLibrary từ ExitInstance trong Win95.

BUG: Khẳng định Khi Calling AfxFreeLibrary từ ExitInstance http://support.microsoft.com/kb/187684

TÌNH TRẠNG: Microsoft đã xác nhận điều này là một lỗi trong Windows 95. Chúng tôi đang nghiên cứu lỗi này và sẽ gửi thông tin mới đây trong Cơ sở tri thức Microsoft khi nó trở nên khả dụng.

+0

Không có điểm giải phóng DLL khi bạn gọi ExitInstance(). Các DLL sẽ tự động được dỡ bỏ dù sao một vài phần nghìn giây sau khi quá trình chấm dứt. –

+0

Vì CWinApp được khai báo trong tệp thực thi chính, nên ExitInstance của nó không được gọi từ DllMain (trong số các lý do khác, bởi vì thực thi không có DllMain). Câu hỏi là do đó tranh luận. –

+0

@RaymondChen, cảm ơn, tôi đã tinh chỉnh câu hỏi của mình là TestApp.dll là một DLL thường được liên kết động với MFC, vì vậy ExitInstance() được gọi để trả lời thư DLL_PROCESS_DETACH trong InternalDllMain. – adshuangjoh

Trả lời

5

Nếu trên thực tế ExitInstance đang được gọi là từ DllMain (có xác nhận của stack trace) thì tất cả các quy tắc cho DllMain áp dụng, bao gồm cả việc cấm tải hoặc dỡ DLL khác đệ quy. (Lưu ý rằng việc đặt CWinApp của bạn trong một DLL là rất bất thường và MFC có thể có các vấn đề khác với nó, chẳng hạn như một trong những lưu ý trong bài viết KB.Không nói rằng có hoặc không có thêm bất kỳ vấn đề ẩn, nhưng thêm một lưu ý bổ sung chú ý.)

+2

Dường như hành vi FreeLibrary đã được thay đổi trong Win8, điều này làm hỏng trạng thái mô-đun MFC, đánh giá cao nếu bạn có thể xem xét vấn đề liên quan trong diễn đàn MSDN [ở đây] (http://social.msdn.microsoft.com/Diễn đàn/en-US/winforms/thread/c872ae41-98e7-43ed-92e8-38f1d68bc5ed) – adshuangjoh

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