Нарушение доступа QueueUserAPC на x86 - PullRequest
1 голос
/ 21 марта 2019

Я пытаюсь использовать QueueUserAPC для асинхронного запуска некоторой функции в определенном потоке. Мой код работает нормально при компиляции для x64, но когда я компилирую и запускаю для x86, я получаю нарушение прав доступа.

В конце моего поста приведен минимальный, полный пример, который показывает, что я пытаюсь сделать (очистка потока и событий для краткости опущена).

На моей машине, когда я компилирую и запускаю для "x64", я получаю ожидаемый результат:

ожидание ...

Асинхронная функция!

ожидания ...

Асинхронная функция!

ожидание ...

ConsoleApplication3.exe (процесс 17100) завершен с кодом 0.

Когда я компилирую и запускаю для "x86", я получаю:

ожидание ...

асинхронная функция!

А затем нарушение доступа, здесь:

if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)

Исключение, выданное в 0x776227FB (ntdll.dll) в ConsoleApplication3.exe: 0xC0000005: Место чтения нарушения доступа 0x36623194.

Что я делаю не так?

Полный пример:

#include "pch.h"
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>

DWORD ThreadFunction(LPVOID param)
{
    while (true)
    {
        printf("waiting...\n");

        if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)
            break;
    }

    ExitThread(0);
    return 0;
}

void AsyncFunction(UINT_PTR param)
{
    printf("async function!\n");
}

int main()
{
    HANDLE hThread, hStopEvent;
    DWORD threadID;

    hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunction, hStopEvent, 0, &threadID);

    Sleep(1000);

    QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);

    Sleep(1000);

    QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);

    Sleep(1000);

    SetEvent(hStopEvent);

    WaitForSingleObject(hThread, INFINITE);
}

1 Ответ

2 голосов
/ 21 марта 2019

В моем определении AsyncFunction есть две ошибки:

1 - тип параметра должен быть ULONG_PTR, , а не UINT_PTR.На самом деле это была ошибка копирования-вставки из моей реальной реализации

2 - Отсутствует соглашение о вызовах из функции

void AsyncFunction(UINT_PTR param) должно быть void CALLBACK AsyncFunction(ULONG_PTR param)

И затем естьнет необходимости в приведении к PAPCFUNC здесь:

QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);

...