为什么va_start失败?

我想创build一些日志,我做了一个类。 不过,我有传递参数的一些问题。

类:

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 

我有两个macros定义:

 #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是导致此,becasue args具有值+ args 0x0052eed8 "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ... char *

有人能帮助我,我做错了什么?

提前致谢!

18.10 / 3 …参数parmN是函数定义的变量参数列表中的最右边参数的标识符( parmN …之前的那个参数)。 如果使用函数,数组或引用类型声明参数parmN ,或者使用与传递没有参数的参数传递的类型不兼容的类型, 则行为是未定义的

强调我的。

使用const char *作为椭圆之前的参数。 正如在另一个答案中指出的那样,行为是不确定的。

另外,它看起来像你的log :: message函数有内存泄漏。 你在不调用free()的情况下使用malloc(),并且在malloc()的返回时也不检查NULL(为什么在C ++程序中使用malloc()

Igor已经给你提供了正式的引用,这里是一个代码片断,用Visual C ++显示了究竟发生了什么。 事情是, va_start需要提前指针来跳过它开始的参数,而引用被有效地作为指针传递时,跳过的大小被视为参数的完整大小。 这使得指针比你期望的更远。

使用va_startA*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:它不能正确地跳过变量,并开始处理你的椭圆在适当的内存位置。