C ++:使用va_list类型作为类成员是否安全?

时间:2011-11-18 11:32:28

标签: c++ variadic-functions

将va_list类型用作类成员是否安全?

以下示例适用于Solaris。它不需要可以跨不同的操作系统移植。但是它可以移植到未来的Solaris版本吗?不同的HW?不同的编译器?还是编译器选项?

class MyFormatString
{
public:
     MyFormatString(const char* formatString, va_list varg);
     ~MyFormatString() { va_end(mVarg); }
     // ... 
     // provide some util functions to operate on the format string
     // ...
private:
     string mFormatString;
     va_list mVarg;
};

MyFormatString::MyFormatString(const char* fmt, va_list varg)
{
    if (fmt)
        mFormatString=fmt;

    va_copy(mVarg, varg);
}

3 个答案:

答案 0 :(得分:6)

不,你只能使用va_list而它所引用的对象在范围内(在函数本身中,或作为参数传递给其他函数),直到你调用va_end为止。 1}}。在从函数返回之前,必须调用va_end,在此之后,va_list不再可用。

从C99,7.15.1.3:“如果在{之前}没有调用va_end宏 返回,行为未定义。“

在C ++ 11中,将可变参数模板或std::tuple视为旧式可变参数函数的类型安全替代方法。

答案 1 :(得分:3)

这在任何平台上都不安全; va_list指向堆栈参数,这些参数在构造函数返回时将过时。考虑使用更多C ++ - ish类型安全的方法来存储参数;可能存储在std::vector<std::string>

答案 2 :(得分:0)

只要在相应的可变参数函数返回之前销毁所有MyFormatString实例,这可能会按预期工作。

然而,根据C标准,它仍然是未定义的行为,因为在调用va_end()的函数返回之前需要调用va_copy(),尽管我不知道它没有的任何实现在va_end()超出范围或相应的可变参数函数返回之前调用va_list就足够了。

如果您正在寻找符合标准的解决方案,请使用va_list*而不是列表的副本。这将分享从同一MyFormatString创建的va_list个实例之间的状态,因此它实际上并不等同。

如果您不想共享状态,则需要手动创建va_list的副本,并将指针传递给构造函数。

va_list是数组类型的平台上使用指针has issues,这可以通过使用C ++引用来避免(显然在C标准中没有考虑到,但应该根据指针语义)。