C++ WIN API ReadFile()返回GetLastError()错误\u无效\u参数

C++ WIN API ReadFile()返回GetLastError()错误\u无效\u参数,c++,winapi,C++,Winapi,我在下面编写了这段代码,它在使用MingWGCC4.7的code::blocks下运行良好。此后,我决定开始使用Visual Studio 2013 express。现在我在调用ReadFile()时遇到一个错误。这似乎是一个无效的参数。我看不出错误,希望这里有人能发现 这些都包装在一个类序列中。从IDE中可以看到,与返回句柄的CreateFile()引用相比,m_hSerial的内存引用是正确的 m_hSerial = CreateFile(m_pchPort,

我在下面编写了这段代码,它在使用MingWGCC4.7的code::blocks下运行良好。此后,我决定开始使用Visual Studio 2013 express。现在我在调用ReadFile()时遇到一个错误。这似乎是一个无效的参数。我看不出错误,希望这里有人能发现

这些都包装在一个类序列中。从IDE中可以看到,与返回句柄的CreateFile()引用相比,m_hSerial的内存引用是正确的

m_hSerial = CreateFile(m_pchPort,
                       GENERIC_READ | GENERIC_WRITE,
                       0,
                       0,
                       OPEN_EXISTING,
                       FILE_FLAG_OVERLAPPED,
                       0);
我这样称呼工作线程

m_hThread = (HANDLE)_beginthreadex(0, 0, &WorkThread, (void*) this, 0, 0);
这是工作线程代码

unsigned int __stdcall Serial::WorkThread(void* pvParam)
{
// This is a pointer to the 'this' serial class.
// Needed to be able to set members of the class in a static class function
Serial * cThis = (Serial*) pvParam;
// Set up the overlapped event
OVERLAPPED ov;
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEvent(0, true, 0, 0);
DWORD dwEventMask = 0;
DWORD dwWait;
HANDLE aHandles[2];
aHandles[0] = cThis->m_hThreadTerminator;
aHandles[1] = ov.hEvent;

SetEvent(cThis->m_hThreadRunning);
while (true)
{
    if (!WaitCommEvent(cThis->m_hSerial, &dwEventMask, &ov))
    {
        assert(GetLastError() == ERROR_IO_PENDING);

    }

    dwWait = WaitForMultipleObjects(2, aHandles, FALSE, INFINITE);
    switch(dwWait)
    {
        case WAIT_OBJECT_0:
        {
            _endthreadex(1);
        }
        case WAIT_OBJECT_0 + 1:
        {
            if (dwEventMask & EV_TXEMPTY)
            {
                ResetEvent(ov.hEvent);
            }
            else if (dwEventMask & EV_RXCHAR)
            {
                // read data here
                DWORD dwBytesRead = 0;
                DWORD dwErrors;
                COMSTAT cStat;
                OVERLAPPED ovRead;
                ovRead.hEvent = CreateEvent(0, true, 0, 0);

                // Get the Bytes in queue
                ClearCommError(cThis->m_hSerial, &dwErrors, &cStat);
                DWORD nSize = cStat.cbInQue;
                // EM_REPLACESEL needs a LPARAM null terminated string, make room and set the CString NULL
                char *szBuf = new char[nSize+1];
                memset(szBuf, 0x00, sizeof(szBuf));

                if (!ReadFile(cThis->m_hSerial, &szBuf, nSize, &dwBytesRead, &ovRead))
                    DWORD err = GetLastError();
                if (dwBytesRead == nSize)
                    SendMessage(cThis->m_hHwnd, WM_SERIAL, 0, LPARAM(&szBuf));

                CloseHandle(ovRead.hEvent); // clean up!!!
                delete[] szBuf;
            }
            // Reset the overlapped event
            ResetEvent(ov.hEvent);
        }
        break;
    }//switch
}

return 0;
}

您要求进行异步操作,但也要求函数告诉您已读取了多少字节。您将
&dwBytesRead
作为倒数第二个参数传递。在执行重叠读取时,将此参数传递到
NULL
。报告说:

如果这是一个异步操作,请对此参数使用NULL,以避免潜在的错误结果

在上述代码中传递
&szBuf
也是错误的。你的意思是通过
szBuf

您也无法初始化重叠的结构。这样做:

OVERLAPPED ovRead = {};
一个更大的问题是,您请求异步访问,但随后以同步方式编写代码。一旦
ReadFile
返回,您就试图从
dwBytesRead
中获取有意义的信息,并关闭放入重叠结构中的事件


如果您真的要异步编写此代码,则需要将代码重新编写为异步。从表面上看,您似乎还没有完全理解重叠I/O的含义,您可能应该切换到非重叠同步I/O。

为什么在调用
ReadFile()
时取消对
szBuf的引用?通过直接传递szBuf,您隐式地执行
&szBuf[0]
,这应该是调用此函数的正确方法@HansPassant你是对的,那是我的错误。把它作为答案贴出来,我会接受的。你可以让大卫更新他的答案。你的意思是通过
&szBuf[0]
*@Vinzenz愚蠢的打字错误,
szBuf
是我的意思,现在已经修复了,谢谢,但是你写了
&szBuf
而不是
szBuf
。而且它只是一种语言。最后,
szBuf
&szBuf[0]
是相同的;)没有“必须”,这只是一个建议。我同意,我可能还没有完全理解它。但这就是目的。感谢您的快速响应,我将研究更改代码。
OVERLAPPED ovRead = {};