Я определил базовый класс, используя std::thread
.Для дочернего класса я выполняю некоторую инициализацию переменных-членов, а затем запускаю поток, используя m_thread.reset(new std::thread(&MyClass::ThreadMain, this));
, где m_thread является членом MyClass.Цель этого класса - прочитать данные из последовательного порта и сообщить об этом родителю.Дескриптор очереди сообщений posix родителя передается в MyClass во время инициализации перед созданием потока.При запуске я получаю исключения и вижу, что переменные-члены, которые были инициализированы до того, как начался поток, кажутся недействительными с помощью функции watch в GDB.
Похоже, что первое сообщение на последовательном порту получено ипрошла проверку, чтобы дозвониться до 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 ++.Любая помощь или идеи будут оценены.