为什么这个sprintf语句崩溃了?

时间:2011-04-12 17:41:04

标签: c++ format

char filebuf[256];
path current = current_path();
std::cout<<"CurrentWorking "<<current<<endl;
string _UserDir = "TTiTraceLogs";
sprintf(filebuf,"%s/%s",current,_UserDir); ///crashing here

如果我只格式化current,那就没关系。

sprintf(filebuf,"%s",current);

输出:

CurrentWorking D:/working/eclipse_projects/sadftp/CollectTTiTraceSept10_1009_174
_higher/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/Release

10 个答案:

答案 0 :(得分:17)

在标准sprintf()函数(以及其他printf() - 类函数)中,%s说明符不适用于C ++ strings;它只适用于C风格的字符串。试试_UserDir.c_str(),它会为const char *指向string的内部数组,因此可以与许多C函数一起使用。

如果current_path()返回的内容不是指向constchar的指针(可能是unsigned char),则还需要转换该值。

答案 1 :(得分:3)

string实际上是std::string吗? path一个boost::filesystem::path?在这种情况下,您应该知道C库函数(如sprintfprintf)不支持像std::string这样的C ++类。那是很自然的。

您需要做的是:

sprintf(filebuf, "%s%s", current.c_str(), _UserDir.c_str());

但是,如果您已经在使用C ++,那么更优雅的解决方案是使用std::stringstreamboost::format。作为奖励,不必在堆栈上分配缓冲区,并担心结果可能比缓冲区更长(这可能导致缓冲区溢出和安全漏洞 - sprintf()可能是其中许多人的罪魁祸首...)。

<强>的std :: stringstream的

std::stringstream filebuf;
filebuf << current_path().c_str() << _UserDir;
std::string filename = filebuf.str();

<强>升压::格式

std::string filename = "%s%s" % current_path().c_str() % _UserDir;

顺便说一下,如果你只想连接目录,那么boost::filesystem::path的“正确”方法就是:

boost::filesystem::path fullPath = current_path() / _UserDir;

是的,/运算符用于添加路径组件。毕竟它们是用斜线分隔的,不是吗?

话虽如此,如果您仍然选择使用旧的C库函数,而不是使用旧的C库函数,请为此,请使用sprintf()。使用稍微更安全的snprintf(),它将最大缓冲区大小作为参数。

答案 2 :(得分:1)

你的一些代码不清楚(例如,究竟是path类型是什么?),但看起来你正试图通过std::string来打印一个C风格的字符串格式化程序(sprintf %s),它完全无效。

看看std::stringstream。此外,对于简单连接,std::string提供+运算符重载。所以你可以做的很简单:

current + "/" + whatever

答案 3 :(得分:1)

sprintf仅适用于char *,不能将其与字符串一起使用。试试_UserDir.c_str(),你应该没问题。

答案 4 :(得分:1)

我不明白为什么你的编译器没有抱怨。您不能将非{POD类型,例如std::stringboost::filepath作为varargs传递;我的编译器说这会在运行时中止,并且任何编译器都会在这里知道你将类类型传递给vararg。 (形式上,它是未定义的行为,但除非编译器以某种方式将其定义为扩展,否则没有理由不至少警告它。)

答案 5 :(得分:0)

当前不是char *指针,它是一个路径,因此可能导致复杂化

另外,sprintf无法像你想要的那样打印到字符串变量。

答案 6 :(得分:0)

current_path多长时间?也许是strlen(current_path)+strlen(_UserDir)+2 > 256

答案 7 :(得分:0)

由于_UserDir是C ++ string,因此您需要获取其C字符串以调用{C}函数sprintf()

sprintf(filebuf,"%s/%s",current,_UserDir.c_str());  // gets C string

另外,什么是path?如果它与typedef的{​​{1}}不同,那么您也不能只char*。可能sprintf()的{​​{1}}超载,这就是operator<<()的原因。

答案 8 :(得分:0)

%s表示C字符串。你有一个C ++字符串。您需要致电.c_str()

答案 9 :(得分:0)

崩溃的原因已经解释了 - 我只能添加一条建议 - 如果可能的话,只需抛弃sprintf并使用字符串流。它会让你的代码变得更好。您不必担心缓冲区的长度或其他错误,例如您遇到的错误。