【问题标题】:var arg list to tempfile, why is it needed?var arg list to tempfile,为什么需要它?
【发布时间】:2010-07-20 13:21:01
【问题描述】:

我在一个类的构造函数中有这段代码(不是我写的),它将一个变量 arg 列表写入一个 tmp 文件。

我想知道为什么需要这样做?在此 ctor 超出范围并且 var arg 列表位于 m_str 向量内后,将删除 tmpfile。

有人可以建议一种更好的方法来执行此操作而不使用 tmpfile 吗?

DString(const char *fmt, ...)
    {

        DLog::Instance()->Log("Inside DString with ellipses");

        va_list varptr;
        va_start(varptr, fmt);
        FILE *f = tmpfile();
        if (f != NULL)
        {
            int n = ::vfprintf(f, fmt, varptr) + 1; 
            m_str.resize(n + 1);
            ::vsprintf(&m_str[0], fmt, varptr);
            va_end(varptr);
        }
        else
            DLog::Instance()->Log("[ERROR TMPFILE:] Unable to create TmpFile for request!");
    }

【问题讨论】:

  • 你能不能改变构造函数的原型来避免使用省略号?
  • ereOn:没有原因它会在我的代码库中导致很多错误。
  • 如果m_strstd::string,则将&m_str[0] 视为指向数组的指针会产生未定义的行为;不保证存储是连续的。如果是std::vector<char>,那没关系。
  • @Mike:理论上你是对的,但只是理论上。 C++0x 增加了一个要求它是连续的,部分原因是似乎没有人知道不连续的实现。
  • 有时修复已知的编译错误(从转换为更好的界面)现在比花费数天时间调试为什么 varargs 参数在一种情况下无法正常工作所花费的时间要少得多。

标签: c++ variadic-functions temporary-files


【解决方案1】:

这是 C++ 代码:我认为您可能在这里尝试解决错误的问题。

如果您考虑使用 C++ 风格的设计而不是继续使用可变参数,那么对临时文件的需求将完全消失。将所有调用站点转换为使用新机制似乎需要做很多工作,但是 varargs 提供了多种错误传递参数的可能性,从而使您面临潜在的错误,更不用说您不能传递非POD 类型。我相信从长期(甚至中期)来看,它会在可靠性、清晰度和易于调试方面获得回报。

尝试实现一个 C++ 风格的流接口,提供类型安全,甚至在需要时禁止某些操作。

【讨论】:

    【解决方案2】:

    它只是把临时文件作为一个地方,可以写出不会溢出的内容,所以它可以测量长度,然后为字符串分配足够的空间,最后将真正的输出存放在字符串中。

    我至少会考虑用 iostreams 风格的界面替换导致这种情况的当前 printf 风格的界面是多么困难,这样可以很容易地避免 iostreams 的通常好处(类型安全、可扩展等)

    编辑:如果更改函数的签名真的很难考虑,那么您可能想用vsnprintf 替换vfprintfvsnprintf 允许您指定缓冲区长度(因此它不会超出缓冲区)并返回如果有足够的空间,将生成的字符数。因此,用法几乎就像您现在一样,但要避免生成临时文件。一旦指定缓冲区长度为 0,您将调用它,使用返回值(NUL 终止符为 +1)来调整缓冲区大小,然后再次调用它并指定正确的缓冲区大小。

    【讨论】:

    • 是否可以在不更改此构造函数签名的情况下进行替换?
    • @Tony:是的。 n = vsnprintf(0, 0, fmt, varptr) + 1 将为您提供长度,而不会随意使用临时文件。
    【解决方案3】:

    它似乎使用临时文件作为 ::vfprintf() 调用的输出位置。它这样做是为了获取格式化字符串的长度(NULL 加 1)。然后将 m_str 的大小调整到足以容纳格式化的字符串,该字符串是从 ::vsprintf() 调用中填充的。

    var arg 列表不在文件或 m_str 中。 printf()(及其变体)的格式化输出在文件和 m_str 中。

    【讨论】:

      【解决方案4】:

      我有一种不安的感觉,但你可以试试:

        FILE *fp=freopen("nul","w", stderr)
        int n = ::vfprintf( fp , fmt, varptr );
        fclose(fp);
      

      (窗口)

      【讨论】:

        猜你喜欢
        • 2011-06-18
        • 1970-01-01
        • 2011-04-02
        • 1970-01-01
        • 1970-01-01
        • 2011-08-09
        • 2013-07-22
        • 2010-12-08
        • 2011-01-15
        相关资源
        最近更新 更多