нагрузка на CPU из-за потоков в dll c++

135
28 апреля 2019, 20:00

есть такого типа код:

bool isActive = false;
DWORD WINAPI Hack_Thread(LPVOID);
DWORD WINAPI Hack_Thread(LPVOID)
{
    while (1) 
    {
        if (GetAsyncKeyState(VK_NUMPAD1))
        {
            MessageBox(0,L"123456",L"654321", MB_OK);
        }
    return 1;
    }
}
DWORD APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, NULL, Hack_Thread, NULL, NULL, NULL);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return true;
}

все работает норм,длл-ка инжектится,но в Proccess Explorer ужасная нагрузка на проц,а приложение крушится после 5-10 минут работы.я новичок в с++,но как я понимаю,происходят бесконечные потоки.как можно решить эту проблему?

Answer 1

Как правильно заметил VTT, в DllMain() нельзя создавать потоки.

Однако ничто не мешает вам отсрочить выполнение своего кода средствами kernel32.dll. Так как у нас нет документированного доступа к loader lock (мьютексу загрузчика модулей), мы не можем определить окончание запрета на создание потоков, а потому вынуждены использовать таймер с достаточно большой задержкой (например, 500 мс).

Так как использовать user32.dll тоже нельзя, таймер у нас будет ядерный:

static HANDLE hTimer;
static VOID CALLBACK TimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
    // Наша полезная нагрузка, вынесенная из DllMain
    CreateThread(NULL, NULL, Hack_Thread, NULL, NULL, NULL);
    // Удаляем объект таймера
    DeleteTimerQueueTimer(NULL, hTimer, NULL);
}
DWORD APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        CreateTimerQueueTimer(&hTimer, NULL, TimerCallback, NULL, 500, 0,
                               WT_EXECUTEINTIMERTHREAD);
        break;
    }
    return true;
}

Флаг WT_EXECUTEINTIMERTHREAD нужен, чтобы наша функция TimerCallback() исполнялась в том же потоке, откуда была вызвана DllMain. Это необязательно, но раз нам всё равно не нужна параллельность (мы не выполняем вычисления, а просто создаём свой постоянный поток), то нет никакой необходимости неявно создавать для неё ещё потоки, подконтрольные не нам, а системе.

Answer 2

Среди того, что нельзя делать в dll main:

вызывать CreateThread

Это можно решить отказавшись от внедрения dll

GetAsyncKeyState кстати тоже не будет нормально работать

READ ALSO
Как использовать glm::ortho?

Как использовать glm::ortho?

Хочу получить результат, как, например, в Blender, в ортогональном режиме

145
Не создаются значения в реестре

Не создаются значения в реестре

У меня есть два QSettings в разных файлах, у одного все значения передаются в реестр, а другого - нет

170
Организация MVC в c++

Организация MVC в c++

Пытаюсь использовать паттерн MVCКак лучше организовать хранение модели и представления в контроллере? Вижу 2 варианта:

144
Немного запутался с типами при создании функции которая принимает строку в виде массива

Немного запутался с типами при создании функции которая принимает строку в виде массива

Не могу понять где наапортачилТолько начал изучать С++ и предомной стоит такая задача, найти количество букы "а" в строке которая передаётся...

119