DllMain内部没有断开的开关/外壳

时间:2010-03-08 19:50:27

标签: c dll winapi switch-statement

我有一个Dllmain,当一个线程附加到这个DLL时,它会分配Thread本地存储。代码如下:

BOOL APIENTRY DllMain(HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved)
{
    LPVOID lpvData; 
    BOOL fIgnore; 

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        onProcessAttachDLL();
        // Allocate a TLS index.
        if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
            return FALSE; 
        // how can it jump to next case???
    case DLL_THREAD_ATTACH:
        // Initialize the TLS index for this thread.
        lpvData = (LPVOID) LocalAlloc(LPTR, MAX_BUFFER_SIZE); 
        if (lpvData != NULL) 
            fIgnore = TlsSetValue(dwTlsIndex, lpvData);  
        break; 
    ...

}

我知道对于主线程,根据Microsoft文档,未输入DLL_THREAD_ATTACH。但是,上面的代码有效。我使用的是VC2005。当我进入调试器时,我看到在ul_reason_for_call = 1后输入DLL_THREAD_ATTACH的情况!怎么会发生这种情况?如果我在DLL_PROCESS_ATTACH块的末尾添加“break”,则DLL无法工作。

这怎么可能发生?

2 个答案:

答案 0 :(得分:8)

如果我理解正确的话,您想知道为什么在输入DLL_PROCESS_ATTACH案例后,DLL_THREAD_ATTACH案件继续执行,而不是在switch结束后执行。< / p>

此行为称为“fall through”,它是标准C.如果没有明确的break语句,则会在下一个case继续执行。

当然,对于第一次看到它的程序员来说这是违反直觉的,所以它是误解甚至错误的常见根源(你可能并不总是知道break是否被故意排除,或者是错误)。因此,在使用此构造时,使用注释明确标记它是一种良好的做法,例如:

switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
    onProcessAttachDLL();
    // Allocate a TLS index.
    if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
        return FALSE; 
    // fall through
case DLL_THREAD_ATTACH:
    // Initialize the TLS index for this thread.
    lpvData = (LPVOID) LocalAlloc(LPTR, MAX_BUFFER_SIZE); 
    if (lpvData != NULL) 
        fIgnore = TlsSetValue(dwTlsIndex, lpvData);  
    break; 
...

答案 1 :(得分:1)

您了解switch语句的工作原理吗?如果你不在案例结尾处休息一下,那么代码就会继续进入下一个案例:

switch (3)
{
case 3:
   cout << "3";
case 4:
   cout << "4";
}

打印3和4。