使用std :: thread

时间:2019-06-22 01:10:00

标签: linux c++11 valgrind stdthread

我已经使用std::thread定义了基类。对于子类,我对成员变量进行一些初始化,然后使用m_thread.reset(new std::thread(&MyClass::ThreadMain, this));启动线程,其中m_thread是MyClass的成员。该类的目的是从串行端口读取数据并向父级报告。在创建线程之前,初始化期间将父级的posix消息队列句柄传递给MyClass。在运行时,我遇到异常,并且看到使用线程启动之前在线程启动之前初始化的成员变量似乎不再有效。

似乎好像收到并通过了验证之后,串行端口上的第一条消息才能到达SendToParent调用。在这次电话会议上,我似乎失去了筹码。我尝试运行cppcheck来查看是​​否有内存泄漏或缓冲区溢出,却一无所获。

void MyClass::ThreadMain(void)
{
   ssize_t bytesRead = 0;
   UINT8 buffer[256];
   UINT8 message[256];
   BOOL partialMessage = FALSE;
   UINT8 messageIndex = 0;
   UINT8 payloadLength = 0;

   // read data from the UART
   while(1)
   {
      // the UART is setup to pend until data is available
      bytesRead = read(m_radioFileDescriptor, buffer, sizeof(buffer));
      if (FAIL == bytesRead)
      {
         LOG_SYSTEM_INFO("UART Read interrupted by a system call");
      }
      else if (bytesRead > 0)
      {
         // build the message
         for(ssize_t i = 0 ; i < bytesRead ; i++)
         {
            if (FALSE == partialMessage)
            {
               // have we found the start of the message?
               if(START_BYTE == buffer[i])
               {
                  // start of new message
                  messageIndex = 0;
                  message[messageIndex] = buffer[i];
                  partialMessage = TRUE;
                  messageIndex++;
               }
            }
            else
            {
               // keep building the message until the expected length is reached
               if(LENGTH_POSITION == messageIndex)
               {
                  // capture the expected message length
                  message[messageIndex] = buffer[i];
                  messageIndex++;
                  payloadLength = buffer[i];
               }
               else
               {
                  message[messageIndex] = buffer[i];
                  messageIndex++;

                  // check for expected length and end byte
                  if((messageIndex == payloadLength) && (END_BYTE == buffer[i]))
                  {
                     // this should be a valid message but need to confirm by checking for a valid checksum
                     UINT8 messageChecksum = message[messageIndex - CHKSUM_POS_FROM_END];
                     UINT8 calculatedChecksum = RadioProtocol::Instance().GenerateRadioChecksum(message, (payloadLength - CHKSUM_POS_FROM_END));
                     if (messageChecksum == calculatedChecksum)
                     {
                        SendToParent(message, payloadLength);
                     }
                     else
                     {
                        LOG_SYSTEM_ERROR("Checksum FAILURE");
                     }

                     // reset for the next message
                     partialMessage = FALSE;
                     messageIndex = 0;
                  }
                  else if((messageIndex == payloadLength) && (END_BYTE != buffer[i]))
                  {
                     // malformed message - throw out and look for start of next message
                     LOG_SYSTEM_ERROR("Bytes read exceeded expected message length");
                     partialMessage = FALSE;
                     messageIndex = 0;
                  }
               }
            }
         } // end for loop of bytes read on the port
      }
      else
      {
         LOG_SYSTEM_INFO("Read returned 0 bytes which is unexpected");
      }
   }
}

void MyClass::SendToParent(UINT8* pMsg, UINT8 size)
{
   if ((pMsg != NULL) && (m_parentQueueHandle > 0))
   {
      // message is valid - pass up for processing
      MsgQueueMessage msgToSend;

      msgToSend.m_msgHeader = UART_MESSASGE;
      bzero(msgToSend.m_msgData, sizeof(msgToSend.m_msgData));
      for (UINT8 i = 0; i < size; i++)
      {
         msgToSend.m_msgData[i] = pMsg[i];
      }

      if (FAIL == msgsnd(m_parentQueueHandle, &msgToSend, sizeof(msgToSend), IPC_NOWAIT))
      {
         LOG_SYSTEM_ERROR("FAILED to send message on queue");
      }
   }
}

这就像我正在执行缓冲区溢出,但是我看不到它。当我在UINT8 messageChecksum = message[messageIndex - CHKSUM_POS_FROM_END];行设置断点时,监视窗口中的所有数据均显示为有效。如果我走到下一行,那么m_parentQueueHandle这个数据就被吹走了。

这是我第一次使用c ++ 11线程,尤其是使用c ++。任何帮助或见解将不胜感激。

1 个答案:

答案 0 :(得分:0)

我想我找到了问题。我添加了一堆printfs,发现正在调用该类的析构函数。在更上游的地方,我将父对象创建为局部变量,并且超出了范围。这导致子级超出范围,但线程仍在运行。我当然需要清理析构函数中的线程。