当我尝试运行对串行端口进行一些基本写入的c文件时,出现错误。我尝试异步运行它,因为写入有时需要很长时间才能传输。我的原始版本使它与WriteFile()命令同步运行,效果很好。我是使用OVERLAPPED的新手,希望能对此有所感激和投入。
我得到的错误是:
Debug Assertion Failed!
<path to dbgheap.c>
Line: 1317
Expression: _CrtIsValidHeapPointer(pUserData)
当第二个写函数被调用时。
在主要方面:
{
//initialized port (with overlapped), DBC, and timeouts
result = write_port(outPortHandle, 128);
result = write_port(outPortHandle, 131);
}
static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
//write completed. check for errors? if so throw an exception maybe?
printf("write completed--and made it to callback function\n");
}
int write_port(HANDLE hComm,BYTE* lpBuf) {
OVERLAPPED osWrite = {0};
// Create this write operation's OVERLAPPED structure's hEvent.
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
// error creating overlapped event handle
return 0;
// Issue write.
if (!WriteFileEx(hComm, &lpBuf, 1, &osWrite, &write_compl )) {
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error and abort.
printf("last error: %ld",GetLastError());
return 0; //failed, return false;
}
else {
// Write is pending.
WaitForSingleObjectEx(osWrite.hEvent, 50, TRUE); //50 ms timeout
return -1; //pending
}
}
else {
return 1; //finished
}
}
抱歉,那不是完整的代码。我也使用了BYTE数组,而不是常量。但是system(“pause”)导致我的调试断言失败错误,并且仔细查看我的代码后,当WriteFileEx()成功时,它从未在重叠结构中为事件设置警报/超时,因此回调函数将永远不会被调用。我解决了这些问题。
我只需要帮助处理/访问在调用ReadFileEx()函数时分配的结构中的单个BYTE(用于存储读取的BYTE,以便可以对其进行处理)。我需要知道如何使用偏移量访问BYTE存储并使重叠的结构为null。将重叠结构设为null就像将其中的句柄设置为INVALID_HANDLE_VALUE一样简单吗?
最佳答案
我认为您有几个问题:
您正在传递一个整数作为指针(您的编译器应对此发出警告,或者最好拒绝编译代码):
将此与write_port的定义进行比较:
上面的陈述不符。稍后,您通过获取BYTE *->“&lpBuf”的地址,将指向lpBuf的指针传递给WriteFileEx函数。这不会导致您认为的结果。
即使已解决此问题,只要写入成功排队但仍无法在50毫秒的超时时间内完成,您仍然会遇到潜在的生命周期问题。
使用重叠的I/O时,需要确保读/写缓冲区和重叠的结构保持有效,直到I/O完成,取消或关联的设备关闭为止。在上面的代码中,您使用指向OVERLAPPED结构的指针,该结构位于对WriteFileEx的调用中的堆栈中。如果WriteFileEx在50毫秒内未完成,则挂起的I/O将引用不存在的OVERLAPPED结构,并且(希望)发生访问冲突(或更糟糕的是,在应用程序中的某个位置静默损坏了堆栈数据)。
处理这些生命周期问题(如果性能不是大问题)的规范方法是使用自定义结构,该结构包括OVERLAPPED结构和一些用于读取/写入数据的存储。发布写操作时分配结构,并从I/O完成例程中取消分配结构。将包含的OVERLAPPED结构的地址传递给WriteFileEx,并使用例如offsetof以从完成例程中的OVERLAPPED地址获取自定义结构的地址。
还要注意,WriteFileEx实际上并不使用hEvent成员IIRC。
编辑:添加了代码示例,请注意:
#include
#include
#include
//...
typedef结构体_MYOVERLAPPED
{
重叠ol;
BYTE缓冲区;
} MYOVERLAPPED,* LPMYOVERLAPPED;
//...
静态void回调write_compl(DWORD dwErrorCode,DWORD dwNumberOfBytesTransfered,LPOVERLAPPED lpOverlapped)
{
如果(NULL == lpOverlapped)
{
断言(!“永远不会发生”);
返回;
}
LPBYTE pOlAsBytes =(LPBYTE)lpOverlapped;
LPBYTE pMyOlAsBytes = pOlAsBytes-offsetof(MYOVERLAPPED,ol);
LPMYOVERLAPPED pMyOl =(LPMYOVERLAPPED)pOlAsBytes;
如果((ERROR_SUCCESS == dwErrorCode)&&
(sizeof(BYTE)== dwNumberOfBytesTransfered))
{
printf(“write%uc\n”,pMyOl-> buffer);
}
别的
{
//处理错误
}
免费(pMyOl);
}
int write_port(HANDLE hComm,BYTE字节){
LPMYOVERLAPPED pMyOl =(LPMYOVERLAPPED)malloc(sizeof(MYOVERLAPPED));
ZeroMemory(pMyOl,sizeof(MYOVERLAPPED));
pMyOl-> buffer =字节;
//发布写入。
如果(!WriteFileEx(hComm,&pMyOl-> buffer,sizeof(BYTE),pMyOl,&write_compl)){
如果(GetLastError()!= ERROR_IO_PENDING){
//WriteFile失败,但没有延迟。报告错误并中止。
免费(pMyOl);
printf(“上一个错误:%ld”,GetLastError());
返回0;//失败,返回false;
}
别的 {
返回-1;//待办的
}
}
别的 {
免费(pMyOl);
返回1;//完成的
}
}