Переключатель / чехол без перерыва внутри DllMain - PullRequest
0 голосов
/ 08 марта 2010

У меня есть Dllmain, который выделяет локальное хранилище потока, когда поток присоединяется к этой DLL. Код как ниже:

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

}

Я знаю, что для основного потока библиотека DLL_THREAD_ATTACH не указана в соответствии с документацией Microsoft. Однако приведенный выше код работал. Я использую VC2005. Когда я вошел в отладчик, я увидел, что после него вошел случай DLL_THREAD_ATTACH, когда ul_reason_for_call = 1! Как это может случиться? Если я добавлю `break 'в конце блока DLL_PROCESS_ATTACH, DLL не будет работать.

Как это может произойти?

Ответы [ 2 ]

8 голосов
/ 08 марта 2010

Если я правильно вас понимаю, вас интересует, почему после ввода случая DLL_PROCESS_ATTACH выполнение продолжается для случая DLL_THREAD_ATTACH, а не после окончания switch.

Это поведение называется «провалиться», и оно является стандартным 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 голос
/ 08 марта 2010

Вы понимаете, как работают операторы switch? если вы НЕ ставите разрыв в конце кейса, то код просто переходит в следующий кейс:

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

печатает как 3, так и 4.

...