gpt4 book ai didi

c++ - vsnprintf 与 GCC 有 %s 段错误

转载 作者:太空狗 更新时间:2023-10-29 23:39:47 25 4
gpt4 key购买 nike

我使用以下方法写入跟踪文件(受 https://stackoverflow.com/a/16046064/283561 启发)

void Tracing::Info( const char*  content, ...)
{
va_list paramList;
va_start( paramList, content );

Tracing::AddRecord(boost::log::trivial::info, content, paramList);
va_end( paramList );
}

void Tracing::AddRecord(boost::log::trivial::severity_level sev, const char* content, va_list paramList)
{
int size = vsnprintf(0, 0, content, paramList) + 1;
if (size > 0)
{
boost::scoped_array<char> formattedString(new char[size]);
vsnprintf(formattedString.get(), size, content, paramList);

boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> & lg = my_logger::get();

BOOST_LOG_SEV(lg, sev) << formattedString.get();
}
}

如果我在Linux(CentOS 7,GCC 4.8.2)下调用方法如下:

Tracing trace;
trace.Error("No %s root tag found!", rootTag.c_str());

它在第二次调用 AddRecord() 中的 vsnprintf 时发生段错误。

如果使用数字格式化程序(例如 %i)调用它,它工作正常。我已经在 Windows (VS2008/2010) 下使用这些方法多年,没有任何问题。

我是否遗漏了一些明显的东西?

最佳答案

你不能像那样重用 va_list;您必须使用 va_copy() 例程来创建一个新的 va_list 实体,并在第二个 vsprintf 上使用它;像这样的东西:

void Tracing::AddRecord(boost::log::trivial::severity_level sev, const char* content, va_list paramList)
{
va_list parm_copy;
va_copy(parm_copy, paramList);
int size = vsnprintf(0, 0, content, paramList) + 1;
if (size > 0)
{
boost::scoped_array<char> formattedString(new char[size]);
vsnprintf(formattedString.get(), size, content, parm_copy);

boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> & lg = my_logger::get();

BOOST_LOG_SEV(lg, sev) << formattedString.get();
}
va_end(parm_copy);
}

问题是第一个 vsnprintf 中使用的操作 va_arg 改变了 va_list 的状态,使其对于在第二个 vsnprintf 中按原样使用。

使用一个小的 C 程序可以很容易地看出这个问题。

#include <stdio.h>
#include <stdarg.h>

void
do_log(const char *item, va_list items)
{
#ifndef EVIL
va_list itemcopy;
va_copy(itemcopy, items);
#else
#define itemcopy items
#endif
int len = vsnprintf(0, 0, item, items);
if (len > 0) {
char buffer[2048];
vsnprintf(buffer, 2047, item, itemcopy);
printf("%s\n", buffer);
}
va_end(itemcopy);
}

int
log_print(const char *item, ...)
{
va_list items;
va_start(items, item);
do_log(item, items);
va_end(items);
return 0;
}

int
main(int argc, char **argv)
{
log_print("These %d %d %d %d", 1, 2, 3, 4);
log_print("Hello %s %s", "Mike", argv[0]);
}

没有 -DEVIL,我得到:

These 1 2 3 4
Hello Mike ./vargs

如果我们使用 CFLAGS=-DEVIL,我会得到输出(在 OSX 上):

These 4 0 0 1570641464
Hello

在其他平台上,它可能会崩溃。

关于c++ - vsnprintf 与 GCC 有 %s 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29369974/

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