2011-11-03 74 views
2

我正在使用重叠I/O读取和写入串行端口。当从命令提示符执行exe时,程序会崩溃(“xxxx.exe遇到问题,需要关闭...”)。使用这个代码块并且是应用程序崩溃的地方在它崩溃之前被调用了好几次,并且工作得很好。奇怪的是,当我在调试模式下从VC++ 2010运行可执行文件时,它不会崩溃。GetOverlappedResult()在运行时崩溃,但从VC++ 2010调试时不崩溃

这是其中GetOverlappedResult()崩溃代码块...

memset(&ov, 0, sizeof(OVERLAPPED)); 
ov.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); 

if(!Comm.Read(lpbBuffer, 1, &dwBytesRead, &ov)) 
    if(GetLastError() != ERROR_IO_PENDING) 
     return FALSE; 

if(!Comm.GetOverlappedResult(&ov,&dwBytesRead,TRUE)) 
{ 
    printf("Resync: Comm.GetOverlappedResult() failed with error code %u\n", GetLastError()); 
    return FALSE; 
} 


Comm.GetOverlappedResult()源

BOOL SerialAsync::GetOverlappedResult(LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait) 
{ 
    printf("made it here\n"); 
    BOOL ret = ::GetOverlappedResult(hComm, lpOverlapped, lpNumberOfBytesTransferred, bWait); 
    printf("made it here too\n"); 
    return ret; 
} 

我有确保hComm,重叠的结构和指向lpNumberOfB的指针ytesTransferred有效。

编辑

添加调试环境变量后,程序将在调试器崩溃...调试器中的#ifdef后打开文件tidtable.c并指向的第一行代码

/*** 
* __set_flsgetvalue - crt wrapper for setting up FlsGetValue pointer in TLS 
* 
* Purpose: 
*  This function helps msvcmXX.dll threadstart and threadstartex APIs 
*  to set FlsGetValue pointer before calling __fls_getvalue. 
* 
*******************************************************************************/ 

_CRTIMP PFLS_GETVALUE_FUNCTION __cdecl __set_flsgetvalue() 
{ 
#ifdef _M_IX86 
    PFLS_GETVALUE_FUNCTION flsGetValue = FLS_GETVALUE; 
    if (!flsGetValue) 
    { 
     flsGetValue = DecodePointer(gpFlsGetValue); 
     TlsSetValue(__getvalueindex, flsGetValue); 
    } 
    return flsGetValue; 
#else /* _M_IX86 */ 
    return NULL; 
#endif /* _M_IX86 */ 
} 

EDIT2

这是正在被调用的函数它终止

之前
BOOL Resync(LPBYTE lpbBuffer) 
{ 
DWORD dwBytesRead; 

while(Comm.Read(lpbBuffer, 1, &dwBytesRead)) 
    if(DDCMP_SOH == *lpbBuffer || DDCMP_ENQ == *lpbBuffer) 
     return TRUE; 

return FALSE; 
} 

这是我已经改变了我AsyncSerial ::阅读()命令是

BOOL SerialAsync::ReadOverlapped(LPBYTE lpbBuffer, DWORD dwSize, LPDWORD dwBytesRead, LPOVERLAPPED lpOverlapped) 
{ 
return ReadFile(hComm, lpbBuffer, dwSize, dwBytesRead, lpOverlapped); 
} 

BOOL SerialAsync::Read(LPBYTE lpbBuffer, DWORD dwSize, LPDWORD dwBytesRead) 
{ 
BOOL bResult = TRUE; 
OVERLAPPED ov; 

memset(&ov, 0, sizeof(OVERLAPPED)); 
ov.hEvent = CreateEvent(NULL,TRUE,TRUE,NULL); 

if(!ReadOverlapped(lpbBuffer,dwSize,dwBytesRead,&ov)) 
    bResult = GetLastError() == ERROR_IO_PENDING; 

if(bResult) 
    bResult = GetOverlappedResult(&ov,dwBytesRead,TRUE); 

CloseHandle(ov.hEvent); 

return bResult; 
} 
+0

我们需要更多的代码。什么'SerialAsync :: Read'看起来像? 'ov'变量的生命周期是多少?接触'ov'的每一段代码是什么? –

回答

0

我终于解决了我的崩溃问题。它似乎与GetOverlappedResult()函数没有直接关系。问题是与线程有关。我在我的程序中有三个线程,主线程,从串口读取的线程和写入串口的线程。我知道正在写的线程在它到达这一点之前已经退出,而不是假设问题出现在我的读取线程中,我应该一直在看我的主线程。

谢谢你的一切帮助。

1

啊C++和它的内存问题。你似乎有堆腐败。它在调试器下工作的原因很可能是由于Debug Heap。这个症状也被称为Heisenbug这是一个错误,当你仔细观察它时会消失。您可以在项目的调试器选项中的流程环境中设置环境变量_NO_DEBUG_HEAP = 1,这样您的应用程序也会在调试器下崩溃。

你提供的代码不包含任何内存分配,所以我不能猜测你的实际问题是什么。

就我个人而言,我会切换到黑暗的一面(C#,F#),垃圾收集器清理了我之后。

+0

它崩溃在这一行上:BOOL ret = :: GetOverlappedResult(hComm,lpOverlapped,lpNumberOfBytesTransferred,bWait); 我认为这与串行端口没有读取数据有关。 –

+0

是访问违规还是其他?你能找出在调试器下实际发生的“崩溃”吗?你可以试试Windbg,它非常强大但不易使用。你是否将重叠实例用于不同的调用?难道是你的班级同时释放了“重叠”结构? –

+0

我不认为这是访问冲突。我注意到,当它崩溃时,手柄的数量会达到最大数量。我已经回顾了代码并确保我关闭了所有的句柄。我确实重复使用重叠的实例进行多个调用。我也试着不重复使用它,每次都创建一个新的,但它在同一个地方崩溃。请参阅我的编辑以了解调试程序指向的内容。 –