当我尝试运行一个对串行端口进行基本写操作的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,而不是常量。但系统(“暂停”)导致我的调试断言失败错误,并仔细查看我的代码后,当WriteFileEx()成功时,它从未在重叠结构中的事件上设置警报/超时,所以永远不会调用回调函数。我解决了这些问题。
我只需要帮助处理/访问一个结构中的单个BYTE,该结构在调用ReadFileEx()函数时分配(用于存储读取的BYTE以便可以处理)。我需要知道如何使用偏移量访问该BYTE存储,并使重叠结构为空。将重叠结构null设置为将其中的句柄设置为INVALID_HANDLE_VALUE这么简单吗?
答案 0 :(得分:2)
我认为你有几个问题:
您正在传递一个整数作为指针(您的编译器应警告此情况,或者最好拒绝编译代码):
result = write_port(outPortHandle,128);
将其与write_port的定义进行比较:
int write_port(HANDLE hComm,BYTE * lpBuf){
以上陈述不符合。稍后,通过获取BYTE * - &gt;的地址,将指针传递给指向WriteFileEx函数的lpBuf指针。 “&安培; lpBuf”。这不会导致您认为它会做什么。
即使您解决了这个问题,只要写入成功排队,但在50毫秒超时内无法完成,您仍会遇到潜在的生命周期问题。
使用重叠I / O时,需要确保读/写缓冲区和重叠结构保持有效,直到I / O完成,取消或相关设备关闭为止。在上面的代码中,您使用指向写入WriteFileEx的堆栈中的OVERLAPPED结构的指针。如果WriteFileEx在50毫秒内没有完成,则挂起的I / O将引用一个不存在的OVERLAPPED结构,并且(希望)会有一个访问冲突(或者更糟糕的是,应用程序中某处的静默损坏的堆栈数据)。 / p>
处理这些生命周期问题的规范方法(如果性能不是一个大问题),是使用包含OVERLAPPED结构的自定义结构和一些用于读取/写入数据的存储。在发布写入时分配结构,并从I / O完成例程中释放结构。将包含的OVERLAPPED结构的地址传递给WriteFileEx,并使用例如offsetof从完成例程中的OVERLAPPED地址获取自定义结构的地址。
另请注意,WriteFileEx实际上并未使用hEvent成员IIRC。
编辑:添加了代码示例,请注意:
#include <stddef.h> #include <assert.h> #include <windows.h> // ... typedef struct _MYOVERLAPPED { OVERLAPPED ol; BYTE buffer; } MYOVERLAPPED, *LPMYOVERLAPPED; // ... static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { if (NULL == lpOverlapped) { assert(!"Should never happen"); return; } LPBYTE pOlAsBytes = (LPBYTE)lpOverlapped; LPBYTE pMyOlAsBytes = pOlAsBytes - offsetof(MYOVERLAPPED, ol); LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)pOlAsBytes; if ((ERROR_SUCCESS == dwErrorCode) && (sizeof(BYTE) == dwNumberOfBytesTransfered)) { printf("written %uc\n", pMyOl->buffer); } else { // handle error } free(pMyOl); } int write_port(HANDLE hComm, BYTE byte) { LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)malloc(sizeof(MYOVERLAPPED)); ZeroMemory(pMyOl, sizeof(MYOVERLAPPED)); pMyOl->buffer = byte; // Issue write. if (!WriteFileEx(hComm, &pMyOl->buffer, sizeof(BYTE), pMyOl, &write_compl )) { if (GetLastError() != ERROR_IO_PENDING) { // WriteFile failed, but isn't delayed. Report error and abort. free(pMyOl); printf("last error: %ld",GetLastError()); return 0; //failed, return false; } else { return -1; //pending } } else { free(pMyOl); return 1; //finished } }
答案 1 :(得分:0)
result = write_port(outPortHandle, 128); result = write_port(outPortHandle, 131);
lpBuf参数必须是指向缓冲区的指针,而不是常量。
e.g。
char buffer;
buffer = 128;
result = write_port(outPortHandle, &buffer);
buffer = 131;
result = write_port(outPortHandle, &buffer);
你真正想要做的是传递缓冲区长度。
e.g。
char buffer[] = { 128, 131 };
result = write_port(outPortHandle, &buffer, sizeof(buffer));
int write_port(HANDLE hComm,BYTE* lpBuf, size_t length) {
...
// Issue write.
if (!WriteFileEx(hComm, &lpBuf, length, &osWrite, &write_compl )) {
...