1

我在一个类的构造函数中有这个代码(不是我写的),它将一个变量 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!");
    }
4

4 回答 4

2

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

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

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

于 2010-07-20T18:19:11.240 回答
1

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

我至少会考虑用 iostreams 样式的接口替换导致这种情况的当前 printf 样式接口是多么困难,这将很容易避免提供 iostreams 的所有常见好处(类型安全,可扩展等)

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

于 2010-07-20T13:30:47.537 回答
0

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

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

于 2010-07-20T13:31:34.710 回答
0

我有一种恶心的感觉,但你可以尝试:

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

(视窗)

于 2010-07-20T13:54:29.423 回答