开发者

Why this sprintf statement crashing? [duplicate]

This question already has answers here: How to read and write a STL C++ string? (3 answers) Closed 4 years ago.
char filebuf[256];
path current = current_path();
std::cout<<"CurrentWorking "<<current<<endl;
string _UserDir = "TTiTraceLogs";
sprintf(filebuf,"%s/%s",current,_UserDir); ///crashing here

If I format only current, then it is ok.

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

Output:

CurrentWorking D:/working/eclipse_projects/sadftp/CollectTTiTraceSept10_1009_174
_higher/xxx开发者_Go百科xxxxxxxxxxxxxxxxxxxxxxxxxxxxx/Release


In the standard sprintf() function (and the other printf()-like functions), the %s specifier doesn't work with C++ stringss; it only works with C-style strings. Try _UserDir.c_str(), which gives you a const char * that points to the internal array of the string and can therefore be used with many C functions.

If current_path() returns something that is not a (possibly const) pointer to char or unsigned char, you need to convert that value too.


Is string actually std::string? And path a boost::filesystem::path? In that case, you should know that C library functions (like sprintf and printf) don't support C++ classes like std::string. That's only natural.

What you need to do is:

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

But a more elegant solution, if you're already using C++, is to either use std::stringstream or boost::format. As a bonus won't have to mess with allocating buffers on the stack and worrying that the result might be longer than the buffer (which may lead to buffer overruns and security exploits - sprintf() is probably the culprit behind many of those...).

std::stringstream

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

boost::format

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

By the way, if you just want to concatenate directories, the 'proper' way to do that with boost::filesystem::path would be:

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

Yes, the / operator is used for adding path components. They are separated by slashes after all, aren't they?

That being said, if you still choose, against all good advice, to use the old C library functions, please, for all that's good in the world, don't use sprintf(). Use the slightly-safer snprintf(), which takes the maximum buffer size as an argument.


Some of your code is unclear (e.g., what on earth is a path type?), but it looks like you're trying to print a std::string via a C-style string formatter (sprintf %s), which is totally invalid.

Look at std::stringstream. Also, for simple concatenation, std::string provides a + operator overload. So you could be doing simply:

current + "/" + whatever


sprintf only works with char*, you cannot use it with strings. Try _UserDir.c_str() and you should be fine.


What I don't understand is why your compiler doesn't complain. You can't pass non-POD types like std::string or boost::filepath as varargs; my compiler says that this will abort at runtime, and any compiler will know here that you're passing class types to a vararg. (Formally, it's undefined behavior, but unless the compiler defines it somehow as an extention, then there's no reason for it not to at least warn.)


current is not a char* pointer, it is a path so it might lead to complication

also, sprintf can't print to string variables like you are trying to do.


How long is current_path? Maybe strlen(current_path)+strlen(_UserDir)+2 > 256.


Since _UserDir is a C++ string, you'll need to get its C string to call sprintf(), which is a C function.

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

Also, what is a path? If it isn't like a typedef for char*, then you can't just sprintf() that either. It may be that operator<<() is overloaded for path, which is why the std::cout works.


%s indicates a C string. You have a C++ string. You need to call .c_str()


The reason of the crash has already been explained - I can only add one piece of advice - just ditch sprintf if possible and use string streams. It will make your code better. You will not have to worry about the length of the buffer or other errors like the one you encountered.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜