我有一个使用select系统调用监视串口的线程,该线程的run函数如下:
void <ProtocolClass>::run()
{
int fd = mPort->GetFileDescriptor();
fd_set readfs;
int maxfd=fd+1;
int res;
struct timeval Timeout;
Timeout.tv_usec=0;
Timeout.tv_sec=3;
//BYTE ack_message_frame[ACKNOWLEDGE_FRAME_SIZE];
while(true)
{
usleep(10);
FD_ZERO(&readfs);
FD_SET(fd,&readfs);
res=select(maxfd,&readfs,NULL,NULL,NULL);
if(res<0)
perror("\nselect failed");
else if( res==0)
puts("TIMEOUT");
else if(FD_ISSET(fd,&readfs))
{//IF INPUT RECEIVED
qDebug("************RECEIVED DATA****************");
FlushBuf();
qDebug("\nReading data into a read buffer");
int bytes_read=mPort->ReadPort(mBuf,1000);
mFrameReceived=false;
for(int i=0;i<bytes_read;i++)
{
qDebug("%x",mBuf[i]);
}
//if complete frame has been received, write the acknowledge message frame to the port.
if(bytes_read>0)
{
qDebug("\nAbout to Process Received bytes");
ProcessReceivedBytes(mBuf,bytes_read);
qDebug("\n Processed Received bytes");
if(mFrameReceived)
{
int no_bytes=mPort->WritePort(mAcknowledgeMessage,ACKNOWLEDGE_FRAME_SIZE);
}//if frame received
}//if bytes read > 0
} //if input received
}//end while
}
问题是当我从这个线程退出时,使用
delete <protocolclass>::instance();
程序因malloc内存损坏的glibc错误而崩溃。在使用gdb检查核心时,发现退出线程时它正在处理数据,从而导致错误。协议类的析构函数如下所示:
<ProtocolClass>::~<ProtocolClass>()
{
delete [] mpTrackInfo; //delete data
wait();
mPort->ClosePort();
s_instance = NULL; //static instance of singleton
delete mPort;
}
这是选择吗?当涉及select时,销毁对象的语义是否会发生变化?有人可以建议一种干净的方法来销毁涉及选择呼叫的线程。
由于
答案 0 :(得分:3)
我不确定你使用的是哪个线程库,但是你应该以某种方式发出它应该退出的信号,而不是杀死它。
最简单的方法是保留一个在线程退出时设置为true的布尔值,并在select()调用上使用超时来定期检查它。
ProtocolClass::StopThread ()
{
kill_me = true;
// Wait for thread to die
Join();
}
ProtocolClass::run ()
{
struct timeval tv;
...
while (!kill_me) {
...
tv.tv_sec = 1;
tv.tv_usec = 0;
res = select (maxfd, &readfds, NULL, NULL, &tv);
if (res < 0) {
// Handle error
}
else if (res != 0) {
...
}
}
您还可以设置一个管道并将其包含在readfds中,然后从另一个线程中写入一些内容。这样可以避免每秒唤醒并立即打倒线程。
此外,如果没有某种锁定,你当然不应该使用类似的布尔变量,......
答案 1 :(得分:0)
删除后,线程是否仍在查看mpTrackInfo?
没有看到代码很难。
但是我认为析构函数应该做的第一件事就是等待任何线程死掉(最好用某种形式的join()来确保它们都被占用)。一旦它们死了,你就可以开始清理数据了。
答案 2 :(得分:0)
你的线程不仅仅是一些成员的内存,所以只删除和计算析构函数是不够的。由于我不知道qt线程,我认为这个链接可以帮助你: trolltech message
答案 3 :(得分:0)
两个可能的问题:
mpTrackInfo
?在等待线程退出之前删除它。线程是否在某处使用了这些数据,甚至可能在它被删除后?run()
中的循环似乎永远运行,这会导致析构函数中的wait()
永远等待。