Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ llMain()。如果您在程序中编写了一个,那么它就是运行的。如果没有,那么CRT中的一个虚拟对象会被链接_C++_Multithreading_Winapi_Dll - Fatal编程技术网

C++ llMain()。如果您在程序中编写了一个,那么它就是运行的。如果没有,那么CRT中的一个虚拟对象会被链接

C++ llMain()。如果您在程序中编写了一个,那么它就是运行的。如果没有,那么CRT中的一个虚拟对象会被链接,c++,multithreading,winapi,dll,C++,Multithreading,Winapi,Dll,当您进行CRT函数调用且CRT未初始化时,所有下注都将取消。您必须删除该#pragma,以便链接器使用正确的入口点。让一个线程管理其他线程,这样就不必一开始就多次加载模块了,这不是更好吗?您没有说问题到底是什么,发布的代码中也没有关于线程的内容。比您上次尝试的更好,但我们确实需要一个新的解决方案。也就是说,一个完整的程序——一个我们可以自己构建和运行的程序,以查看出了什么问题。它还必须尽可能短,因此请删除演示问题不需要的任何代码。如果是这样,则调用LoadLibrary是违反规则的。可能加载程序

当您进行CRT函数调用且CRT未初始化时,所有下注都将取消。您必须删除该#pragma,以便链接器使用正确的入口点。

让一个线程管理其他线程,这样就不必一开始就多次加载模块了,这不是更好吗?您没有说问题到底是什么,发布的代码中也没有关于线程的内容。比您上次尝试的更好,但我们确实需要一个新的解决方案。也就是说,一个完整的程序——一个我们可以自己构建和运行的程序,以查看出了什么问题。它还必须尽可能短,因此请删除演示问题不需要的任何代码。如果是这样,则调用LoadLibrary是违反规则的。可能加载程序锁已断开,这将导致所有新线程死锁。PS:您真的应该尝试修复潜在的问题,即为什么应用程序过早地卸载DLL,而不是试图扰乱实例计数。“在另一个线程内”实际上并不意味着什么。所有代码都是由一个线程执行的,所以任何时候你创建另一个线程时,你已经作为一个线程执行了。如何解决此问题以加载
SecondThread
函数?让我们把MSDN放在一边,因为我们是程序员,我们的目标是解决不清楚的问题。我所知道的防止DllMain处理过程中死锁的唯一解决方案是从DllMain中取出造成死锁的函数性(如创建线程或加载DLL),并将其放入单独的导出函数中,这必须由DLL的客户端显式调用。@RobertFrost@RoMa post链接非常清楚地表明,
DllMain在加载程序锁定时被调用。。。您不能在DllMain中调用任何直接或间接尝试获取加载程序锁的函数。。。你不应该。。。调用LoadLibrary或LoadLibraryEx(直接或间接)。这可能会导致死锁或崩溃。
这不是任何灰色区域,它是经过处理的。你所谓的“问题”是无法解决的。你需要修改设计。@dxiv我是个固执的程序员,这使我在事业上获得了成功。当有人说这不可能时,总会有办法的。我将努力解决这个问题,并在我回答时更新我的问题。。。我必须绕开这一点,无意冒犯,但我并不在乎MSDN怎么说。@RoMa,事实上,如果你知道自己在做什么,在DllMain中调用CreateThread是安全的(而且通常是必要的)。唯一可能的问题是,直到DllMain退出,线程才真正开始运行,因此如果您做了一些愚蠢的事情,比如等待来自它的消息,那么就会死锁。(但LoadLibrary是另一回事。)问题是,当我将其从DllMain中移动时,我的DllMain中出现了一个错误。我通过Rundll32运行程序,当我运行时,它会给我一个
条目notfound:EntryPoint
错误。即使我在代码中有一个
extern“C”\uu declspec(dllexport)void\uu stdcall入口点(HWND、HINSTANCE、LPSTR、INT)
。请参阅。您需要使用DEF文件删除导出名称中的装饰,或者告诉
rundll32
要调用的函数是
_EntryPoint@16
。但是,如果您使用
rundll32
启动DLL,那么确实不需要IncrementReference(),因为在EntryPoint()返回之前
rundll32
不会卸载DLL。(完全删除DllMain并从EntryPoint执行所有操作也更明智。)事实上,
\u DllMainCRTStartup()
不仅初始化CRT,还确保满足某些语言保证。一种常见的此类保证是在应用程序运行之前初始化具有静态存储持续时间的对象<代码>\u DllMainCRTStartup()初始化这些对象。
BOOL IncrementReference( HMODULE hModule )
{
    if ( hModule == NULL )
        return FALSE;

    TCHAR ModulePath[ MAX_PATH + 1 ];
    if ( GetModuleFileName( hModule , ModulePath , MAX_PATH ) == 0 )
        return FALSE;

    if ( LoadLibrary( ModulePath ) == NULL )
        return FALSE;

    return TRUE;
}
// dllmain.cpp : Defines the entry point for the DLL application.
#pragma comment( linker , "/Entry:DllMain" )
#include <Windows.h>
#include <process.h>

UINT CALLBACK SecondThread( PVOID pParam )
{
    MessageBox( NULL , __FUNCTION__ , "Which Thread?" , 0 );
    return 0;
}

UINT CALLBACK FirstThread( PVOID pParam )
{
  MessageBox( NULL , __FUNCTION__ , "Which Thread?" , 0 );
  _beginthreadex(0, 0, &SecondThread, 0, 0, 0);
  return 0;
}

BOOL IncrementReference( HMODULE hModule )
{
    if ( hModule == NULL )
        return FALSE;

    TCHAR ModulePath[ MAX_PATH + 1 ];
    if ( GetModuleFileName( hModule , ModulePath , MAX_PATH ) == 0 )
        return FALSE;

    if ( LoadLibrary( ModulePath ) == NULL )
        return FALSE;

    return TRUE;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        {
            if (IncrementReference(0))    
                _beginthreadex(0, 0, &FirstThread, 0, 0, 0);
        }
        break;
    }
    return TRUE;
}
extern "C" __declspec(dllexport) void __stdcall EntryPoint(HWND, HINSTANCE, LPSTR, INT)
{
      MessageBoxA( NULL , __FUNCTION__ , "Which Thread?" , 0 );
}
rundll32 testdll.dll,_EntryPoint@16
   #pragma comment( linker , "/Entry:DllMain" )