GetExitCodeThread(hThread, (PDWORD) &uSum);

本文介绍了一个使用递归实现的求和函数,并通过创建单独的线程来避免堆栈溢出的问题。文章展示了如何利用结构化异常处理(SEH)捕获并处理堆栈溢出异常。
///////////////////////////////////////////////////////////////////////////////


// An example of calling Sum for uNum = 0 through 9
// uNum: 0 1 2 3  4  5  6  7  8  9 ...
// Sum:  0 1 3 6 10 15 21 28 36 45 ...
UINT Sum(UINT uNum) {

   // Call Sum recursively.
   return((uNum == 0) ? 0 : (uNum + Sum(uNum - 1)));
}


///////////////////////////////////////////////////////////////////////////////
//*

LONG WINAPI FilterFunc(DWORD dwExceptionCode) {

   return((dwExceptionCode == STATUS_STACK_OVERFLOW) 
      ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH);
}

//*/
///////////////////////////////////////////////////////////////////////////////


// The separate thread that is responsible for calculating the sum. 
// I use a separate thread for the following reasons:
//    1. A separate thread gets its own 1 MB of stack space.
//    2. A thread can be notified of a stack overflow only once.
//    3. The stack's storage is freed when the thread exits.
DWORD WINAPI SumThreadFunc(PVOID pvParam) {
	Sleep(2000);
   // The parameter pvParam, contains the number of integers to sum.
   UINT uSumNum = PtrToUlong(pvParam);

   // uSum contains the summation of the numbers from 0 through uSumNum. 
   // If the sum cannot be calculated, a sum of UINT_MAX is returned.
   UINT uSum = UINT_MAX;

   __try {
      // To catch the stack overflow exception, we must 
      // execute the Sum function while inside an SEH block.
      uSum = Sum(uSumNum); 
   }
   __except (FilterFunc(GetExceptionCode())) {
      // If we get in here, it's because we have trapped a stack overflow. 
      // We can now do whatever is necessary to gracefully continue execution
      // This sample application has nothing to do, so no code is placed 
      // in this exception handler block.
   }

   // The thread's exit code is the sum of the first uSumNum 
   // numbers, or UINT_MAX if a stack overflow occurred.
   return(uSum);
}


///////////////////////////////////////////////////////////////////////////////


void CMyExitCodeDlg::OnBtnCalc() 
{
         // Get the number of integers the user wants to sum.
         UINT uSum = GetDlgItemInt( IDC_NUM_INPUT, NULL, FALSE);

         // Create a thread (with its own stack) that is
         // responsible for performing the summation.
         DWORD dwThreadId;
		 /*
         HANDLE hThread = chBEGINTHREADEX(NULL, 0, 
            SumThreadFunc, (PVOID) (UINT_PTR) uSum, 0, &dwThreadId);
		*/

/*#define chBEGINTHREADEX(psa, cbStack, pfnStartAddr, \
   pvParam, fdwCreate, pdwThreadId)                 \
*/
      HANDLE hThread = ((HANDLE)_beginthreadex(
         (void *)        (NULL),
         (unsigned)      (0),
         (PTHREAD_START) (SumThreadFunc),
         (void *)        ((PVOID) (UINT_PTR) uSum),
         (unsigned)      (0), 
         (unsigned *)    (&dwThreadId)));

         // Wait for the thread to terminate.
         //WaitForSingleObject(hThread, INFINITE);

         // The thread's exit code is the resulting summation.
         GetExitCodeThread(hThread, (PDWORD) &uSum);
		while(STILL_ACTIVE==uSum)
		  {
			  static unsigned int i=0;
			  
			  SetDlgItemInt(IDC_SHOW_ANSWER, ++i, FALSE);
			  Sleep(200);
			 GetExitCodeThread(hThread, (PDWORD) &uSum);
		  }

         // Allow the system to destroy the thread kernel object
         CloseHandle(hThread);

         // Update the dialog box to show the result.
         if (uSum == UINT_MAX) {
            // If result is UINT_MAX, a stack overflow occurred.
            SetDlgItemText(IDC_SHOW_ANSWER, TEXT("Error"));
            chMB("The number is too big, please enter a smaller number");
         } else {
            // The sum was calculated successfully; 
            SetDlgItemInt(IDC_SHOW_ANSWER, uSum, FALSE);
         }	
}

#pragma once #include "MsGlobal.h" #include <windows.h> #include <process.h> #include "hid/hidapi.h" #pragma comment (lib,"setupapi.lib") using namespace std; struct sBuff { sBuff() { stop = 0; len = 0; memset(udata, 0, 10240); } int stop; int len; unsigned char udata[10240]; }; class ComBase { public: ComBase(); ~ComBase(); int InitUSB(unsigned short vid, unsigned short pid); int OpenUSB(unsigned short vid, unsigned short pid); void CloseUSB(); public: int SendMsg(unsigned char* Send, size_t nLength); int ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength); int getDevStatus() { return handle ? 0 : 1; } hid_device *getHID() { return this->handle; } sBuff *getBuff() { return this->m_pBuff; } void setBuff(sBuff *pBuff) { this->m_pBuff = pBuff; } private: hid_device *handle; sBuff *m_pBuff; }; #include "ComBase.h" #include "algorithm/GCS_Encrypt.h" #include "files/logFile.h" ComBase::ComBase() { handle = nullptr; m_pBuff = new sBuff(); } ComBase::~ComBase() { if (handle) CloseUSB(); delete m_pBuff; m_pBuff = nullptr; } int ComBase::InitUSB(unsigned short vid, unsigned short pid) { if (hid_init())//实际上不调用它hid_enumerate和下面的hid_open也会自动调用 return -1; hid_device_info* Hids, *HidsCopy;//一个用于接收设备信息的单链表,另一个用来遍历,该结构体使用unicode编码,所以下面都要用unicode处理方式 Hids = hid_enumerate(vid, pid);//获取vid为0x154F,pid为0x4304的HID设备链表,这里如果都是0就是获取所有的HID设备 HidsCopy = Hids; LPCWSTR wpSerialNumber = L"\0";//用来去重,一个hid设备一般有多个端点,因此会读到多个 while (HidsCopy) { if (CompareStringW(LOCALE_INVARIANT, NORM_LINGUISTIC_CASING, wpSerialNumber, -1, HidsCopy->serial_number, -1) != CSTR_EQUAL)//去重 { xPrintf((LPCTSTR)HidsCopy->serial_number); wpSerialNumber = HidsCopy->serial_number;//我这里只需要序列号,实际上这个结构体还有很多数据,可以参考官方的实例 } HidsCopy = HidsCopy->next; } hid_free_enumeration(Hids);//释放设备链表 return 0; } /********************************************************* 函数名称: OpenUSB(LPCTSTR PscSerialNumber) 函数功能: 打开USB-HID设备 输入参数: 参数1: LPCTSTR PscSerialNumber - HID设备的序列号 返回值: 成功 - 0 失败 - -1 ********************************************************/ int ComBase::OpenUSB(unsigned short vid, unsigned short pid) { if (MsGlobal::m_VirtualVer == VER_VIRTUAL) { return 0; } if (handle) CloseUSB(); handle = hid_open(vid, pid, NULL);//打开指定vid、pid、序列号的设备 if (!handle) { xPrintf("无法打开USB设备"); hid_exit(); return -1; } // 将hid_read()函数设置为非阻塞。 if (hid_set_nonblocking(handle, 1) != 0)// 1启用非阻塞 0禁用非阻塞。 { xPrintf("设置非阻塞失败"); hid_close(handle); hid_exit(); return -2; } return 0; } //关闭USB-HID设备 /********************************************************* 函数名称: CloseUSB(hid_device*& handle) 函数功能: 关闭USB-HID设备 输入参数: 参数1: hid_device*& handle - 操作句柄 ********************************************************/ void ComBase::CloseUSB() { if (MsGlobal::m_VirtualVer == VER_VIRTUAL) { return; } if (handle) { hid_close(handle); hid_exit(); } handle = nullptr;//这里将指针置空,增强安全性 } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // 线程执行的函数 unsigned int WINAPI ThreadSendMsg(LPVOID lpThreadParameter) { ComBase *m_pDev = (ComBase *)lpThreadParameter; if (!m_pDev) { xPrintf("lpThreadParameter error"); return -1; } sBuff *pBuff = m_pDev->getBuff(); if (!pBuff || pBuff->len == 0) { xPrintf("getBuff error"); return -2; } hid_device *handle = m_pDev->getHID(); if (handle == INVALID_HANDLE_VALUE) { xPrintf("getHID error"); return -3; } // 读取数据并清空缓存 int leftNum = 1; while (leftNum) { unsigned char buf[1024]; memset(buf, 0, 1024); leftNum = hid_read_timeout(handle, buf, sizeof(buf), 0); if (leftNum < 0) { xPrintf("hid_read_timeout error"); return -4; } } // 此处对消息进行加密,从第三个字节开始 GCS_Msg_Encryption(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]); // 此处分包,目前支持64个字节(加上id一共65个字节) int size = 64; int packs = pBuff->len / size * size; if (pBuff->len % size != 0) { packs++; } int result = 0; for (int i = 0; i < packs; i++) { int rlen = size; if (i * size > pBuff->len) rlen = pBuff->len - (i - 1) * size; UCHAR OutputReport[65]; memset(OutputReport, 0, 65); memcpy(&OutputReport[1], &pBuff->udata[i * size], rlen); int iResp = hid_write(handle, OutputReport, 65); if (iResp < 0) { xPrintf("hid_write error"); result = -5; break; } } ExitThread(result); } int ComBase::SendMsg(unsigned char* Send, size_t nLength) { /// 初始化缓存 this->m_pBuff->stop = 0; this->m_pBuff->len = nLength; memcpy(this->m_pBuff->udata, Send, nLength); /// 启动发送线程 unsigned int dwThreadID; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadSendMsg, (void *)this, 0, &dwThreadID); if (hThread == NULL) { xPrintf("_beginthreadex Error!"); return -1; } /// 线程阻塞 DWORD wr = WaitForSingleObject(hThread, 3000); switch (wr) { case WAIT_FAILED: { xPrintf("thread wait failed"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -2; } break; case WAIT_TIMEOUT: { xPrintf("thread wait timeout"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -3; } break; default: break; } /// 获取线程函数的返回值 DWORD dwExitCode; GetExitCodeThread(hThread, &dwExitCode); if (dwExitCode != 0) { xPrintf("thread exit code error"); CloseHandle(hThread); return -4; } CloseHandle(hThread); return 0; } // 线程执行的函数 unsigned int WINAPI ThreadReceiveMsg(LPVOID lpThreadParameter) { ComBase *m_pDev = (ComBase *)lpThreadParameter; if (!m_pDev) { xPrintf("lpThreadParameter error"); return -1; } sBuff *pBuff = m_pDev->getBuff(); if (!pBuff || pBuff->len != 0) { xPrintf("getBuff error"); return -2; } hid_device *handle = m_pDev->getHID(); if (handle == INVALID_HANDLE_VALUE) { xPrintf("getHID error"); return -3; } int result = 0; while (!pBuff->stop) { UCHAR recvDataBuf[1024]; memset(recvDataBuf, 0, 1024); int len = hid_read(handle, recvDataBuf, 65); if (len > 0) { memcpy(&pBuff->udata[pBuff->len], recvDataBuf, len); pBuff->len += len; if (pBuff->udata[0] != 0xE5) {/// 无效数据 xPrintf("read data exception\n"); result = -4; break; } else {/// 有效数据 int msglen = pBuff->udata[1] + 2; if (msglen <= pBuff->len) {/// 接收完成 // 此处对消息进行解密,从第三个字节开始 GCS_Msg_Decrypt(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]); //计算crc16 uint16_t crc = crc16_modbus(&pBuff->udata[0], msglen - 2); uint8_t crc_low = crc & 0xFF; uint8_t crc_high = (crc >> 8) & 0xFF; if (crc_low != pBuff->udata[msglen - 1] || crc_high != pBuff->udata[msglen - 2]) { xPrintf("crc error\n"); result = -5; break; } else { xPrintf("read data finish\n"); result = 0; break; } } else {/// 接收未完成 xPrintf("read data unfinish\n"); continue; } } } } ExitThread(result); } int ComBase::ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength) { /// 刷新缓存 this->m_pBuff->stop = 0; this->m_pBuff->len = 0; memset(this->m_pBuff->udata, 0, 10240); /// 启动接收线程 unsigned int dwThreadID; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadReceiveMsg, (void *)this, 0, &dwThreadID); if (hThread == NULL) { xPrintf("_beginthreadex error!"); return -1; } /// 线程阻塞 DWORD wr = WaitForSingleObject(hThread, 3000); switch (wr) { case WAIT_FAILED: { xPrintf("thread wait failed"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -2; } break; case WAIT_TIMEOUT: { xPrintf("thread wait timeout"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -3; } break; default: break; } /// 获取线程函数的返回值 DWORD dwExitCode; GetExitCodeThread(hThread, &dwExitCode); if (dwExitCode != 0) { xPrintf("thread exit code error"); CloseHandle(hThread); return -4; } /// 根据协议拷贝有效的消息部分 nLength = this->m_pBuff->udata[1] + 2; memcpy(pReceiveBuf, this->m_pBuff->udata, nLength); CloseHandle(hThread); return 0; }#pragma once #include "MsGlobal.h" #include <windows.h> #include <process.h> #include "hid/hidapi.h" #pragma comment (lib,"setupapi.lib") using namespace std; struct sBuff { sBuff() { stop = 0; len = 0; memset(udata, 0, 10240); } int stop; int len; unsigned char udata[10240]; }; class ComBase { public: ComBase(); ~ComBase(); int InitUSB(unsigned short vid, unsigned short pid); int OpenUSB(unsigned short vid, unsigned short pid); void CloseUSB(); public: int SendMsg(unsigned char* Send, size_t nLength); int ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength); int getDevStatus() { return handle ? 0 : 1; } hid_device *getHID() { return this->handle; } sBuff *getBuff() { return this->m_pBuff; } void setBuff(sBuff *pBuff) { this->m_pBuff = pBuff; } private: hid_device *handle; sBuff *m_pBuff; }; #include "ComBase.h" #include "algorithm/GCS_Encrypt.h" #include "files/logFile.h" ComBase::ComBase() { handle = nullptr; m_pBuff = new sBuff(); } ComBase::~ComBase() { if (handle) CloseUSB(); delete m_pBuff; m_pBuff = nullptr; } int ComBase::InitUSB(unsigned short vid, unsigned short pid) { if (hid_init())//实际上不调用它hid_enumerate和下面的hid_open也会自动调用 return -1; hid_device_info* Hids, *HidsCopy;//一个用于接收设备信息的单链表,另一个用来遍历,该结构体使用unicode编码,所以下面都要用unicode处理方式 Hids = hid_enumerate(vid, pid);//获取vid为0x154F,pid为0x4304的HID设备链表,这里如果都是0就是获取所有的HID设备 HidsCopy = Hids; LPCWSTR wpSerialNumber = L"\0";//用来去重,一个hid设备一般有多个端点,因此会读到多个 while (HidsCopy) { if (CompareStringW(LOCALE_INVARIANT, NORM_LINGUISTIC_CASING, wpSerialNumber, -1, HidsCopy->serial_number, -1) != CSTR_EQUAL)//去重 { xPrintf((LPCTSTR)HidsCopy->serial_number); wpSerialNumber = HidsCopy->serial_number;//我这里只需要序列号,实际上这个结构体还有很多数据,可以参考官方的实例 } HidsCopy = HidsCopy->next; } hid_free_enumeration(Hids);//释放设备链表 return 0; } /********************************************************* 函数名称: OpenUSB(LPCTSTR PscSerialNumber) 函数功能: 打开USB-HID设备 输入参数: 参数1: LPCTSTR PscSerialNumber - HID设备的序列号 返回值: 成功 - 0 失败 - -1 ********************************************************/ int ComBase::OpenUSB(unsigned short vid, unsigned short pid) { if (MsGlobal::m_VirtualVer == VER_VIRTUAL) { return 0; } if (handle) CloseUSB(); handle = hid_open(vid, pid, NULL);//打开指定vid、pid、序列号的设备 if (!handle) { xPrintf("无法打开USB设备"); hid_exit(); return -1; } // 将hid_read()函数设置为非阻塞。 if (hid_set_nonblocking(handle, 1) != 0)// 1启用非阻塞 0禁用非阻塞。 { xPrintf("设置非阻塞失败"); hid_close(handle); hid_exit(); return -2; } return 0; } //关闭USB-HID设备 /********************************************************* 函数名称: CloseUSB(hid_device*& handle) 函数功能: 关闭USB-HID设备 输入参数: 参数1: hid_device*& handle - 操作句柄 ********************************************************/ void ComBase::CloseUSB() { if (MsGlobal::m_VirtualVer == VER_VIRTUAL) { return; } if (handle) { hid_close(handle); hid_exit(); } handle = nullptr;//这里将指针置空,增强安全性 } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // 线程执行的函数 unsigned int WINAPI ThreadSendMsg(LPVOID lpThreadParameter) { ComBase *m_pDev = (ComBase *)lpThreadParameter; if (!m_pDev) { xPrintf("lpThreadParameter error"); return -1; } sBuff *pBuff = m_pDev->getBuff(); if (!pBuff || pBuff->len == 0) { xPrintf("getBuff error"); return -2; } hid_device *handle = m_pDev->getHID(); if (handle == INVALID_HANDLE_VALUE) { xPrintf("getHID error"); return -3; } // 读取数据并清空缓存 int leftNum = 1; while (leftNum) { unsigned char buf[1024]; memset(buf, 0, 1024); leftNum = hid_read_timeout(handle, buf, sizeof(buf), 0); if (leftNum < 0) { xPrintf("hid_read_timeout error"); return -4; } } // 此处对消息进行加密,从第三个字节开始 GCS_Msg_Encryption(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]); // 此处分包,目前支持64个字节(加上id一共65个字节) int size = 64; int packs = pBuff->len / size * size; if (pBuff->len % size != 0) { packs++; } int result = 0; for (int i = 0; i < packs; i++) { int rlen = size; if (i * size > pBuff->len) rlen = pBuff->len - (i - 1) * size; UCHAR OutputReport[65]; memset(OutputReport, 0, 65); memcpy(&OutputReport[1], &pBuff->udata[i * size], rlen); int iResp = hid_write(handle, OutputReport, 65); if (iResp < 0) { xPrintf("hid_write error"); result = -5; break; } } ExitThread(result); } int ComBase::SendMsg(unsigned char* Send, size_t nLength) { /// 初始化缓存 this->m_pBuff->stop = 0; this->m_pBuff->len = nLength; memcpy(this->m_pBuff->udata, Send, nLength); /// 启动发送线程 unsigned int dwThreadID; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadSendMsg, (void *)this, 0, &dwThreadID); if (hThread == NULL) { xPrintf("_beginthreadex Error!"); return -1; } /// 线程阻塞 DWORD wr = WaitForSingleObject(hThread, 3000); switch (wr) { case WAIT_FAILED: { xPrintf("thread wait failed"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -2; } break; case WAIT_TIMEOUT: { xPrintf("thread wait timeout"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -3; } break; default: break; } /// 获取线程函数的返回值 DWORD dwExitCode; GetExitCodeThread(hThread, &dwExitCode); if (dwExitCode != 0) { xPrintf("thread exit code error"); CloseHandle(hThread); return -4; } CloseHandle(hThread); return 0; } // 线程执行的函数 unsigned int WINAPI ThreadReceiveMsg(LPVOID lpThreadParameter) { ComBase *m_pDev = (ComBase *)lpThreadParameter; if (!m_pDev) { xPrintf("lpThreadParameter error"); return -1; } sBuff *pBuff = m_pDev->getBuff(); if (!pBuff || pBuff->len != 0) { xPrintf("getBuff error"); return -2; } hid_device *handle = m_pDev->getHID(); if (handle == INVALID_HANDLE_VALUE) { xPrintf("getHID error"); return -3; } int result = 0; while (!pBuff->stop) { UCHAR recvDataBuf[1024]; memset(recvDataBuf, 0, 1024); int len = hid_read(handle, recvDataBuf, 65); if (len > 0) { memcpy(&pBuff->udata[pBuff->len], recvDataBuf, len); pBuff->len += len; if (pBuff->udata[0] != 0xE5) {/// 无效数据 xPrintf("read data exception\n"); result = -4; break; } else {/// 有效数据 int msglen = pBuff->udata[1] + 2; if (msglen <= pBuff->len) {/// 接收完成 // 此处对消息进行解密,从第三个字节开始 GCS_Msg_Decrypt(secret::KEY_COMMUNICATION, sizeof(secret::KEY_COMMUNICATION), &pBuff->udata[2], pBuff->udata[1]); //计算crc16 uint16_t crc = crc16_modbus(&pBuff->udata[0], msglen - 2); uint8_t crc_low = crc & 0xFF; uint8_t crc_high = (crc >> 8) & 0xFF; if (crc_low != pBuff->udata[msglen - 1] || crc_high != pBuff->udata[msglen - 2]) { xPrintf("crc error\n"); result = -5; break; } else { xPrintf("read data finish\n"); result = 0; break; } } else {/// 接收未完成 xPrintf("read data unfinish\n"); continue; } } } } ExitThread(result); } int ComBase::ReceiveMsg(unsigned char* pReceiveBuf, size_t& nLength) { /// 刷新缓存 this->m_pBuff->stop = 0; this->m_pBuff->len = 0; memset(this->m_pBuff->udata, 0, 10240); /// 启动接收线程 unsigned int dwThreadID; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadReceiveMsg, (void *)this, 0, &dwThreadID); if (hThread == NULL) { xPrintf("_beginthreadex error!"); return -1; } /// 线程阻塞 DWORD wr = WaitForSingleObject(hThread, 3000); switch (wr) { case WAIT_FAILED: { xPrintf("thread wait failed"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -2; } break; case WAIT_TIMEOUT: { xPrintf("thread wait timeout"); this->m_pBuff->stop = 1; CloseHandle(hThread); return -3; } break; default: break; } /// 获取线程函数的返回值 DWORD dwExitCode; GetExitCodeThread(hThread, &dwExitCode); if (dwExitCode != 0) { xPrintf("thread exit code error"); CloseHandle(hThread); return -4; } /// 根据协议拷贝有效的消息部分 nLength = this->m_pBuff->udata[1] + 2; memcpy(pReceiveBuf, this->m_pBuff->udata, nLength); CloseHandle(hThread); return 0; } 这段代码实现了什么功能,让我读懂每一行代码
09-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值