1. 程序描述:程序中使用了deque::pop_front和deque::push_back操作(这两个函数存在于两个不同的函数中,但是都使用semop进行临界保护,并且他们被放到了共享库中)。
2. 现象描述:程序崩溃,每次都会提示pop_front段错误。有时崩溃的程序会在终端打印堆栈信息,eg:*** glibc ... double free or corrupt(xxx) *** ......。
3. 调试流程:有网友谈到这个问题,都认为是没有上锁导致,deque操作不是线程安全的,所以必须上锁。查看程序有semop系列函数加持,用法和各网友用法一样。且程序中没有使用多线程,前面提到的线程安全问题应该不存在。
于是根据core文件提示跟到了pop_front之内部实现,发现每次都会在调用_M_pop_front_aux处崩溃。该函数只用在首迭代器与尾迭代器差值为1时被调用(这与代码不符,代码中先判断deque::size > 1024时才会调用一次pop_front)。说明semop系列锁机制可能没有起到作用。于是在锁的入口和出口处设置打印,果然验证了前述的判断。于是换了一种锁机制,使用pthread_mutex_lock系列操作继续测试。证明没有问题。再次查看semop系列操作,和网上各博客用法一致,遂不得而知。
4. 总结:虽然在同一个线程下,deque之移除操作和插入操作理论上虽然顺序执行(无论单核多核),但是如果不能保证插入和移除整个操作为原子操作那么还是要上锁的,而semop系列函数不是很靠谱,至少按照网友的指示是这样。推荐使用更为简单的pthread_mutex_xxx系列函数。