DLL中的CreateThread提前终止

问题描述

我正在尝试从控制台应用程序加载DLL。简单的控制台应用程序如下所示:

#include <iostream>
#include <windows.h>

int main(){
    HMODULE handleDll = LoadLibraryA("C:\\Tools\\TestDLL.dll");
    if (handleDll)
    {
        std::cout << "DLL Loaded at Address: " << handleDll << std::endl;
    }

    FreeLibrary(handleDll);
}

该DLL可以通过POP弹出一个MessageBox,但它只是在屏幕上闪烁而不是等待用户输入。 DLL代码如下:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>

DWORD WINAPI ThreadProc( __in  LPVOID lpParameter )
{
    MessageBox(NULL,L"Hi From The Thread!",L"Pop a Box!",MB_OK);
    return 0;
}

extern "C" __declspec(dllexport) 
VOID PopMessageBox()
{
    DWORD ThreadID;
    HANDLE handleThread; 

    handleThread = CreateThread(NULL,ThreadProc,&ThreadID);
    CloseHandle(handleThread);
}

BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        PopMessageBox();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

我的问题是..如何使线程函数中的代码完全执行而不会过早终止或引起痛苦的死锁?很抱歉,我的英语不熟练和经验不足。

解决方法

原因是您在DllMain中做不安全的事情:您正在呼叫CreateThread

DllMain中,您对自己在main中可以做什么的限制是非常有限的,documentation会发出这样的事实:

在DLL入口点中可以安全进行的操作有很大的限制。有关在DllMain中调用不安全的特定Windows API的信息,请参阅常规最佳实践。如果除了最简单的初始化之外还需要其他任何东西,则可以在DLL的初始化函数中进行。您可以要求应用程序在DllMain运行之后且在调用DLL中的任何其他函数之前调用初始化函数。

警告将您链接到“一般最佳实践”,其中包括“ [c]所有CreateThread。如果您不与其他线程同步,则创建线程可以工作,但是这样做是有风险的。” >

即使没有与其他线程同步的风险,此代码在其他方面也很不稳定:例如,您的FreeLibrary只需调用file = open('AllCongress.txt',"r") lines = file.readlines() lines = lines.split(' ') for x in lines: if(x.startswith("Mr."): *code here* elif(x.startswith("Ms."): *code here* 并退出。您在DLL中产生的线程(实际上可能是执行中的线程)将具有应该未映射运行的代码。您实际上是从地毯下面拉地毯!