我使用以下方法写入跟踪文件(受/sf/answers/1123224511/启发)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
如果我在Linux下使用以下方法调用该方法(CentOS 7,GCC 4.8.2):
Tracing trace;
trace.Error("No %s root tag found!", rootTag.c_str());
Run Code Online (Sandbox Code Playgroud)
它在AddRecord()中第二次调用vsnprintf时会出现段错误.
如果使用数字格式化程序(例如%i)调用它,它可以正常工作.我已经在Windows(VS2008/2010)下使用这些方法多年没有问题.
我错过了一些明显的东西吗?
Pet*_*esh 10
你不能重用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);
}
Run Code Online (Sandbox Code Playgroud)
问题在于,va_arg第一次使用的操作vsnprintf改变了状态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]);
}
Run Code Online (Sandbox Code Playgroud)
没有-DEVIL,我得到:
These 1 2 3 4
Hello Mike ./vargs
Run Code Online (Sandbox Code Playgroud)
如果我们使用CFLAGS=-DEVIL,我得到输出(在OSX上):
These 4 0 0 1570641464
Hello
Run Code Online (Sandbox Code Playgroud)
在其他平台上,它可能崩溃.
| 归档时间: |
|
| 查看次数: |
826 次 |
| 最近记录: |