日志文件输出问题 - 字符串和c_str之间的区别 - C ++

时间:2011-12-26 09:55:46

标签: c++ string logging

我正在尝试完成我的日志记录类。我从头开始编写它,不希望使用任何类型的替代库。我的问题在于我的记录器在输出std::string时遇到问题,只有当我用string.c_str()函数表示它时才有效。

这是我的日志文件输出功能:

void Log::writeSuccess(char * text,...)
{
    // Grab the variables and insert them
    va_list ap;
    va_start(ap, text);
    char buff[BUFFER_SIZE];
    vsnprintf(buff, sizeof(buff), text, ap);

    // Output to the log
    logfile << "<-!-> " << buff << endl;
}

以下是对我的日志类对象的示例调用(忽略调用的无用性):

string test("This is a test string!");
errorLog.writeSuccess("Output: %s", test);

我最终得到随机字符和输出乱码。

但是,当我将test附加.c_str()字符串时,它会正确输出文字。

我试图避免使用cstrings的全部原因是因为我知道它们不是跨平台的,我正在开发我的客户端来支持所有主要的操作系统。

总结:

  1. 我的日志输出功能有什么问题?你认为有什么方法可以改进吗?

  2. 我一般应该避免使用c_strings吗?

2 个答案:

答案 0 :(得分:2)

在将std::string传递给vsnprintf时,您会发现随机乱码,因为格式说明符"%s"是C字符串 - char*

std::string 类型为char*,但std::string.c_str() 类型为char*vsnprintf基本上会读取{em>它假定的地址所指向的char是C字符串的开头,直到NUL字符'\0'为止

std::string推入堆栈并作为参数传递给vsnprintf不是指向char的指针,但是vsnprintf只会将这些字节视为地址并从该地址开始读取char s / bytes,导致未定义的行为。

printf函数族不是类型安全的,因为它们依赖于格式字符串和变量参数列表,这就是为什么你的代码会编译但你会得到意想不到的结果。


当您使用格式说明符printf时,底线是期望char*的{​​{1}}系列函数。

我还认为你将C样式字符串("%s")与特定于Microsoft的CString类混淆。 C样式字符串根本不会在不同平台上引起问题;文字char[]是C样式字符串("This is a test string!")。

答案 1 :(得分:1)

使用变量参数调用函数时,必须使用简单类型。对于string,您必须使用c_str()。没有解决方法。 MFC的CString旨在让您可以直接使用它,但这是微软的决定,也是他们设计的一部分。

编辑:正如我在调用具有可变参数的函数时所说,必须使用string :: c_str()。但是,您可以使用类似boost::format()之类的函数来代替具有可变参数的类似C函数,并使用参数提供运算符%。这也使您可以更好地控制参数的排序,这对i18n非常方便。