开发者

Switch/case without break inside DllMain

开发者 https://www.devze.com 2022-12-22 02:29 出处:网络
I have a Dllmain that allocates Thread local storage when a thread attaches to this DLL. Code as below:

I have a Dllmain that allocates Thread local storage when a thread attaches to this DLL. Code as below:

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 开发者_如何学Gothis thread.
        lpvData = (LPVOID) LocalAlloc(LPTR, MAX_BUFFER_SIZE); 
        if (lpvData != NULL) 
            fIgnore = TlsSetValue(dwTlsIndex, lpvData);  
        break; 
    ...

}

I know that for the main thread, the DLL_THREAD_ATTACH is not entered, as per Microsoft Documentation. However, the above code worked. I am using VC2005. When I entered the debugger, I saw that after it entered DLL_THREAD_ATTACH case when ul_reason_for_call = 1! How can that happen? If I add `break' at the end of DLL_PROCESS_ATTACH block, the DLL failed to work.

How can this happen?


If I understand you correctly, you are wondering why, after entering the DLL_PROCESS_ATTACH case, the execution continues on the DLL_THREAD_ATTACH case, instead of after the end of the switch.

This behaviour is called "fall through", and it is standard C. Without an explicit break statement, the execution continues on the next case.

Of course, it is quite counterintuitive for programmers who see it the first time, so it is a constant source of misunderstanding and even bugs (you may not always know whether the break was left out intentionally, or by mistake). It is considered good practice, therefore, when using this construct, to mark it explicitly with a comment, like:

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; 
...


Do you understand how switch statements work? if you do NOT put a break at the end of the case, then the code just continues into the next case:

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

prints both 3 and 4.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号