我想创建一些日志记录,然后我创建了一个类。但是我将参数传递给它有一些问题。
班级:
namespace debug
{
class log
{
private: // Members
const std::string context;
int Type;
public: // Methods
void message( int Type, const std::string& message, ... );
public: // Constructor, Destructor
log( const std::string& context, int Type );
~log();
};//class log
}//namespace debug
namespace debug
{
void log::message( int Type, const std::string& message, ... )
{
va_list args;
int len;
char *buffer;
va_start( args, message );
len = _vscprintf( message.c_str(), args ) + 1; // _vscprintf doesn't count terminating '\0'
buffer = ( char* )malloc( len * sizeof( char ) );
vsprintf_s( buffer, len, message.c_str(), args );
va_end( args );
}//log::message
}//namespace debug
我定义了两个宏:
#define DEBUG_METHOD( Type ) debug::log _debugLog( __FUNCTION__, Type );
#define DEBUG_MESSAGE( Type, debug_message, ... ) { _debugLog.message( Type, debug_message, ##__VA_ARGS__ ); }
我在这样的函数中使用它们:
BOOL test( BOOL *bTestVal)
{
DEBUG_METHOD( INFO );
DEBUG_MESSAGE( INFO, "Argument1 = '%s'", BoolToString( ( BOOL )*bTestVal) );
//here comes some work...
}
不幸的是我总是收到错误。此行len = _vscprintf( message.c_str(), args ) + 1;
始终抛出错误。我认为va_start
导致此问题,因为args
的值为+ args 0x0052eed8 "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ... char *
有人可以帮我解决我的错误吗?
提前致谢!
答案 0 :(得分:6)
18.10 / 3 ...参数
parmN
是函数定义的变量参数列表中最右边的参数的标识符(恰好在......之前)。如果使用函数,数组或引用类型声明参数parmN
,或者使用与传递没有参数的参数时产生的类型不兼容的类型,行为未定义。
强调我的。
答案 1 :(得分:3)
Igor已经为您提供了正式引用,这里是一个代码片段,用Visual C ++显示确切的结果。问题是va_start
需要将指针前进以跳过它开始的参数,并且虽然引用有效地作为指针传递,但跳过大小被视为参数的完整大小。这使指针远远超出预期。
使用va_start
与A*
和A&
进行比较:
class A
{
public:
char B[1024];
};
void C(int f, A* a, ...)
{
va_list Arguments;
va_start(Arguments, a);
int d = va_arg(Arguments, int);
_tprintf(_T("0x%p, 0x%p, %d, %d\n"), &f, Arguments, (char*) &f - (char*) Arguments, d);
}
void E(int f, A& a, ...)
{
va_list Arguments;
va_start(Arguments, a);
int d = va_arg(Arguments, int);
_tprintf(_T("0x%p, 0x%p, %d, %d\n"), &f, Arguments, (char*) &f - (char*) Arguments, d);
}
int _tmain(int argc, _TCHAR* argv[])
{
A a;
C(0, &a, 1234);
E(0, a, 1234);
你得到的输出是这样的:
0x0018F9E0, 0x0018F9EC, -12, 1234
0x0018F9E0, 0x0018FEC0, -1248, -858993460
两个函数的堆栈帧都在相同的地址(预期)开始,然后va_start的结果将指针移动不同的距离,这与A
类的大小相关(12对1248)。
这就是为什么你不能将va_start与引用类型的参数一起使用:它无法正确跳过变量并开始在适当的内存位置处理你的省略号。
答案 2 :(得分:2)
使用const char *作为省略号之前的参数。正如在另一个答案中指出的那样,行为是未定义的。
此外,看起来你的log :: message函数有内存泄漏。你在不调用free()的情况下使用malloc(),并且在返回malloc()时也没有检查NULL(为什么你在C ++程序中使用malloc())