这个礼拜调试多线程偶现了一个栈溢出的问题:
#0 0x55ba07 (/home/sunliwang/mysource/Obotcha/ObotchaTestSuite/testUtil/testConcurrent/testFuture/mytest+0x55ba07)
#1 0x7f4008dad147 (../../../../out/lib/libobotcha.so+0x9ea147)
#2 0x7f4008dad17f (../../../../out/lib/libobotcha.so+0x9ea17f)
#3 0x7f4008dad2c8 (../../../../out/lib/libobotcha.so+0x9ea2c8)
....
#244 0x55bb73 (/home/sunliwang/mysource/Obotcha/ObotchaTestSuite/testUtil/testConcurrent/testFuture/mytest+0x55bb73)
#245 0x7f4008dad147 (../../../../out/lib/libobotcha.so+0x9ea147)
#246 0x7f4008dad17f (../../../../out/lib/libobotcha.so+0x9ea17f)
#247 0x7f4008dad2c8 (../../../../out/lib/libobotcha.so+0x9ea2c8)
....
很奇怪的现象,从frame1,frame2,frame3开始循环的调用,直到栈溢出。用addr2line定位,发现frame1,frame2,frame3对应的函数都是~_WaitingTask()这个析构函数。当时还挺奇怪的,为啥会出现析构函数的递归呢?
查看了WaitingTask的使用的场景,发现我使用WaitingTask做了一个链表:
WaitingTask1->next = WaitingTask2->next = WaitingTask3->next = WaitingTask4->next..
|
header
每个next都指向了下一个任务。当去任务的时候就从头部获取WaitingTask1。这个时候,由于我没有把WaitingTask1->next设定为空,所以WaitingTask2的引用计数一直是2(WaitingTask1的next,和标记头部的header)。如果waitingTask1不释放的话,WaitingTask2就不会被释放,接着WaitingTask3也不会被释放....导致整个链表都没有释放。直到WaitingTask1处理完成,释放,整个链表依次开始释放,导致堆栈溢出。。。。
之前所有的介绍智能指针的文章里面都没有介绍过这种异常。哈哈,大家平时使用的时候可能需要注意,能释放的尽量要早释放!!!
最后修改的代码如下:
long interval =
(mTaskPool->nextTime - st(System)::currentTimeMillis());
if (interval <= 0) {
mCurrentTask = mTaskPool;
mTaskPool = mTaskPool->next;
mCurrentTask->next = nullptr; //remove task link for stack overflow
} else {
mTaskWaitCond->wait(mTaskMutex, interval);
continue;
}
添加了mCurrentTask->next = nullptr这句,提前释放~。