C++ CancelIoEx:函数指针类型def

C++ CancelIoEx:函数指针类型def,c++,function,pointers,typedef,cancelio,C++,Function,Pointers,Typedef,Cancelio,以下代码是从MS Async Filter复制的。假设以下代码正在调用CancelIo或CancelIoEx。我看不出CancelIoEx在哪里。假设typedef代表CancelIoEx,但从未调用过。行bResult=(pfncancelionex)(m_hFile,NULL)的具体内容正在做什么 // Cancel: Cancels pending I/O requests. HRESULT CFileStream::Cancel() { CAutoLock lock(&m

以下代码是从MS Async Filter复制的。假设以下代码正在调用CancelIo或CancelIoEx。我看不出CancelIoEx在哪里。假设typedef代表CancelIoEx,但从未调用过。行
bResult=(pfncancelionex)(m_hFile,NULL)的具体内容正在做什么

// Cancel: Cancels pending I/O requests.
HRESULT CFileStream::Cancel()
{
    CAutoLock lock(&m_CritSec);

    // Use CancelIoEx if available, otherwise use CancelIo.

    typedef BOOL (*CANCELIOEXPROC)(HANDLE hFile, LPOVERLAPPED lpOverlapped);

    BOOL bResult = 0;
    CANCELIOEXPROC pfnCancelIoEx = NULL;


    HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll");

    if (hKernel32){

        //propably bad code !!! Take Care.
        bResult = (pfnCancelIoEx)(m_hFile, NULL);

        FreeLibrary(hKernel32);
    }
    else {

        bResult = CancelIo(m_hFile);
    }

    if (!bResult) {

        return HRESULT_FROM_WIN32(GetLastError());
    }
    return S_OK;
}

假设这就是所有的代码,它有一个严重的错误。这:

CANCELIOEXPROC pfnCancelIoEx = NULL;
pfnCancelIoEx
定义为指向签名与
CancelIoEx
匹配的函数的指针。指针初始化为空值,明显的目的是稍后将其指向
CancelIoEx

该函数是在
Kernel32.dll
中定义的,因此加载该函数是合乎逻辑的下一步。如果此操作成功,代码应继续执行以下操作:

pfnCancelIoEx = GetProcAddress(hKernel32, "CancelIoEx");
然后它应该检查结果。然而,这两者都不能做到

接下来,在这一行:

bResult = (pfnCancelIoEx)(m_hFile, NULL);

它尝试调用由
pfncancelionex
指向的函数。但是,此指针永远不会更改其初始空值,因此这将尝试取消对空指针的引用,导致未定义的行为,并可能导致崩溃。

这真的是所有代码吗?我假设
pfncancelionex
在被调用之前会被分配到。类似于
pfncancelionex=GetProcAddress(…“CancelIoEx”…)
yes就是这样。我附上完整的功能(一些评论是我的)是的,我绝对同意你。。。但是我认为直接调用CancelIoEx会更容易,而不是做一个编程循环来完成同样的事情:-)我不明白重点!!!你?@Maverick如果该功能在某些情况下不可用(例如,如果它仅在某些版本的Windows上可用),你通常会使用这种技巧。Hoever,根据它的文档,
CancelIoEx
从Windows 95开始就可以使用,所以这里的情况似乎不是这样。。。我想不出其他原因。函数CancelIoEx在Vista和更高版本的操作系统中可用(您可以在上检查),但在这种情况下,我不认为仅仅检查它是否可以加载Kernel32.dll就表明它是Vista操作系统或实现了特定的函数。我说的对吗?@Maverick哎呀,我打开的MSDN页面错了。感谢您更正功能可用性。代码实际上并不是在调用
CancelIoEx
(即使它恰好在加载的
Kernel32
中),而是去引用一个空指针。是的,我同意你关于指针去引用的观点,当然这是错误的。原始代码本身应该使用代码“if(hKernel32)”检查新CancelIoEx的可用性,如果是真的,则很明显CancelIoEx存在并被调用(某种方式也是错误的)。现在,在hKernel32检查失败的情况下,正如您在代码中看到的,它被称为旧的CancelIo。正如我所说,这段代码是错误的,因为您无法确定CancelIoEx的可用性或存在性,只需检查Kernel32.dll是否可以毫无问题地加载即可。