我下面的代码是一个简单的错误记录系统,其行为方式类似于 printf。
我的所有代码都在 gtest 环境中运行良好,但现在当我退出程序中的一个确定性点(我的一个测试)时,它堆栈崩溃了。在我写这篇文章之前,我的代码一直运行良好,这是我第一次尝试 cstdarg,所以它是最可疑的。
MyMutex error_lock;
#define MAX_ERR_MSG_SIZE 128
#define MAX_ERRORS 3
class ErrorQueue
{
std::queue<char*> errors;
std::list<char*> old_errors;
public:
void push(char * msg)
{
if (errors.size() >= MAX_ERRORS)
{
pop();
}
errors.push(msg);
}
void pop()
{
if (old_errors.size() >= MAX_ERRORS)
{
delete [] old_errors.front();
old_errors.pop_front();
}
old_errors.push_back(errors.front());
errors.pop();
}
char * front()
{
return errors.front();
}
size_t size()
{
return errors.size();
}
~ErrorQueue()
{
while(!errors.empty())
{
delete [] errors.front();
errors.pop();
}
while (!old_errors.empty())
{
delete [] old_errors.front();
old_errors.pop_front();
}
}
};
static ErrorQueue errors;
void WriteCallError(const char * error_message, ...)
{
char err_buffer[MAX_ERR_MSG_SIZE];
va_list args;
va_start(args,error_message);
std::vsnprintf(err_buffer,MAX_ERR_MSG_SIZE,error_message,args);
va_end(args);
char * err_string = new char[MAX_ERR_MSG_SIZE];
memcpy(err_string,err_buffer,MAX_ERR_MSG_SIZE);
{
error_lock.Lock();
errors.push(err_string);
error_lock.Unlock();
}
}
我在代码的其他地方多次调用 WriteCallError ,经过一定次数后它会呕吐并告诉我我的堆栈已粉碎。
我的错在哪里?cstdarg 和 gtest 之间有什么奇怪的交互吗?这里有足够的信息吗?
编辑:使用一个简单的 main 我尝试将其隔离:
int main (int argc, char ** argv)
{
int i = 0;
while (1)
{
WriteCallError("Breaks on %d",i++);
}
}
这不会导致堆栈粉碎。