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