gpt4 book ai didi

c++ - gtest 和 cstdarg 之间是否存在不良交互,或者我真的错过了这里的堆栈粉碎?

转载 作者:行者123 更新时间:2023-11-28 03:22:53 24 4
gpt4 key购买 nike

我下面的代码是一个简单的错误记录系统,其行为方式类似于 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++);
}

}

这不会导致堆栈崩溃。

最佳答案

我认为你的问题是,如果你正在写入的数据超出了你指定的限制,vsnprintf 不会将终止 nul 字符写入数组。当您稍后访问此 C 字符串时,由于没有终止符,它会读取超出有效数据末尾的部分并进入未知内存。

您没有在测试中发现这一点,因为您没有超过 128 个字符的限制。

快速修复是确保在使用 vsnprintf 后正确终止数组:

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);

// Fix here
err_buffer[MAX_ERR_MSG_SIZE - 1] = 0;

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();
}
}

关于c++ - gtest 和 cstdarg 之间是否存在不良交互,或者我真的错过了这里的堆栈粉碎?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14970601/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com