我写的一个服务器程序,在运行大约8小时候,出现
#1 0x00002adde5c9a853 in _int_free () from /lib64/libc.so.6
#2 0x00002adde5c9a99c in free () from /lib64/libc.so.6
下面一级堆栈是
m_queuefreep->pop();
下面是源码:
data_t *try_get_free_data()
{
boost::mutex::scoped_try_lock lock(m_free_mutex);
if(!lock.owns_lock())
{
return NULL;
}
if(m_queuefreep->empty())
{
return NULL;
}
data_t* datap = m_queuefreep->front();
m_queuefreep->pop();
return datap;
};
这个队列,我只是用来存放结构体指针,而且已经加锁保护;m_queuefreep->pop()的过程中,会调用free()函数,free一个指针类型;这没有必要free的阿。
经过仔细分析,可以确认自己的代码没有问题。百度到了一篇文章:《 谁知道malloc_consolidate是个什么函数》这位老兄,也碰到类似的问题,他提出的解决办法是替换queue。
《 std::queue.pop()的怪异问题:多线程环境下,pop()将调用对象的析构函数》这位老兄,也一样,碰到过这个问题。
这位老兄的模板类写的非常好,收录如下:
#include <stdexcept> // for debug purpose
template <typename item, unsigned int qsize>
class queue
{
public:
item data[qsize];
unsigned int rp,wp;
bool full;
queue(): rp(0),wp(0),full(false) {}
bool empty() { return ((rp == wp) && (!full)); }
unsigned int size()
{
if(!full) return (wp-rp+qsize)%qsize;
else return qsize;
}
item& front()
{
if(empty()) throw;
return data[rp];
}
item& back()
{
if(empty()) throw;
return data[(wp-1+qsize)%qsize];
}
void push(const item dd)
{
if(full) throw;
data[wp] = dd;
wp = (wp+1)%qsize;
if(wp == rp) full = true;
}
void pop()
{
if(empty()) throw;
rp = (rp + 1)%qsize;
full = false;
}
};
template <typename item, unsigned int qsize>
class stack
{
public:
item data[qsize];
unsigned int p;
stack(): p(0){}
bool empty() { return (p == 0);}
unsigned int size() { return p; }
item& top()
{
if(empty()) throw;
return data[p-1];
}
void push(const item dd)
{
if(p==qsize) throw;
data[p++] = dd;
}
void pop()
{
if(empty()) throw;
p--;
}
};
并略加修改:
/*
* myqueue.h
* meant to replace the STL queue.
* Created on: 2010-3-19
* Author: guoqiang
*/
#ifndef MYQUEUE_H_
#define MYQUEUE_H_
#include <stdlib.h>
#include <exception>
#include <stdexcept> // for debug purpose
using namespace std;
template <typename item>
class gqueue
{
public:
gqueue(int capacity): m_rp(0), m_wp(0), m_full(false)
{
m_capacity = capacity;
m_datap = (item*)malloc(sizeof(item)*m_capacity);
if(m_datap == NULL)
{
throw(exception());
}
}
virtual ~gqueue() throw()
{
if(m_datap)
{
free(m_datap);
m_datap = NULL;
}
}
bool empty()
{
return ((m_rp == m_wp) && (!m_full));
}
unsigned int size()
{
if(!m_full)
{
return (m_wp-m_rp+m_capacity)%m_capacity;
}
else
{
return m_capacity;
}
}
item& front()
{
if(empty())
{
throw;
}
return m_datap[m_rp];
}
item& back()
{
if(empty())
{
throw;
}
return m_datap[(m_wp-1+m_capacity)%m_capacity];
}
void push(const item dd)
{
if(m_full)
{
throw;
}
m_datap[m_wp] = dd;
m_wp = (m_wp+1)%m_capacity;
if(m_wp == m_rp)
{
m_full = true;
}
}
void pop()
{
if(empty())
{
throw;
}
m_rp = (m_rp + 1)%m_capacity;
m_full = false;
}
private:
unsigned int m_capacity;
// item data[qsize];
item* m_datap;
unsigned int m_rp;
unsigned int m_wp;
bool m_full;
};
#endif /* MYQUEUE_H_ */
替换了到自己的工程当中,编译,执行;等待中,等待出错,或者永远不出错。
注:本文转自 一个萝卜的同名Blog。