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

发布于 2024-12-16 21:46:45 字数 561 浏览 1 评论 0原文

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

以下示例适用于 Solaris。它不需要在不同的操作系统之间移植。但它可以移植到未来的 Solaris 版本吗?硬件不同?不同的编译器?或者编译器选项?

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);
}

Is it safe to use a va_list type as a class member?

The below example works in Solaris. It doesn't need to be portable across different operating systems. But is it portable to future Solaris versions? Different HW? Different compilers? Or compiler options?

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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

九局 2024-12-23 21:46:45

不,您只能在 va_list 所引用的对象在作用域内(在函数本身中,或作为参数传递给其他函数)时使用 va_list,直到您调用 >va_end。您必须在从函数返回之前调用va_end,之后va_list将不再可用。

从 C99,7.15.1.3 开始:“如果 va_end 宏在
返回,行为未定义。”

在 C++11 中,考虑可变参数模板或 std::tuple 作为老式可变参数函数的类型安全替代方案。

No, you can only use the va_list while the objects it refers to are in scope (in the function itself, or passed as an argument to other functions), up to the point at which you call va_end. You must call va_end before returning from the function and, after that point, the va_list is no longer usable.

From C99, 7.15.1.3: "if the va_end macro is not invoked before the
return, the behavior is undefined."

In C++11, consider variadic templates or std::tuple as type-safe alternatives to old-school variadic functions.

兔小萌 2024-12-23 21:46:45

这在任何平台上都不安全; va_list 指向堆栈参数,当构造函数返回时,该参数将被废弃。考虑使用更 C++ 类型安全的方法来存储参数;可能存储在 std::vector 中。

This is not safe on any platform; va_list points to the stack arguments which will be obsolete when the constructor returns. Consider using a more C++-ish type-safe method to store the arguments; probably storing in a std::vector<std::string>.

温折酒 2024-12-23 21:46:45

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

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

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

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

使用指针有问题 在 va_list 是数组类型的平台上,可以通过使用 C++ 引用来避免这种情况(这显然没有在 C 标准中考虑,但应该根据指针语义进行操作)。

This will probably work as expected as long as all MyFormatString instances are destroyed before the corresponding variadic function returns.

However, it's still undefined behaviour according to the C standard as va_end() needs to be called before the function which invoked va_copy() returns, though I don't know of any implementations where it doesn't suffice to call va_end() before the va_list goes out of scope or the corresponding variadic function returns.

If you're looking for a standards-compliant solution, use a va_list* instead of a copy of the list. This will share state between MyFormatString instances created from the same va_list, though, so it is not really equivalent.

If you do not want to share state, you'll need to manually create a copy of the va_list and pass a pointer to that to your constructor.

Using pointers has issues on platforms where va_list is an array type, which can be avoided by using C++ references instead (which obviously aren't accounted for in the C standard, but should behave according to pointer semantics).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文