Why this sprintf statement crashing? [duplicate] - c++

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/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/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.

Related

converting a string to a c string

m working on some homework but don't even know where to start on this one. If you could can you throw me in the right direction. This is what i'm suppose to do
Write your own version of the str_c function that takes a C++ string as an argument (with the parameter set as a constant reference variable) and returns a pointer to the equivalent C-string. Be sure to test it with an appropriate driver.
There are different possibilities to write such a function.
First, take a look at the C++ reference for std::string, which is the starting point for your problem.
In the Iterator section on that page, you might find some methods which can help you to get the string character by character.
It can also help to read the documentation for the std::string::c_str method, you'd like to imitate: string::c_string. It's important to understand, how the system works with normal C-strings (char*):
Due to the fact, that a C-string has now length- or size-attribute, a trick is used to determine the end of the string: The last character in the string has to be a '\0'.
Make sure you understand, that a char* string can also be seen as array of characters (char[]). This might help you, when understanding and solving your problem.
as we know, C-string is null-terminated array of char. you can put char by char from std::string to an array of char, and then closed with '\0'. and remember a pointer to a char (char*) is also representation of array of char. you can use this concept

C++: Format not a string literal and no format arguments [duplicate]

This question already has answers here:
warning: format not a string literal and no format arguments
(3 answers)
Closed 8 years ago.
I've been trying to print a string literal but seems like I'm doing it wrong, since I'm getting a warning on compilation. It's probably due to wrong formatting or my misunderstanding of c_str() function, which I assume should return a string.
parser.y: In function ‘void setVal(int)’:
parser.y:617:41: warning: format not a string literal and no format arguments [-Wformat-security]
Line 617:
sprintf(temp, constStack.top().c_str());
Having those declarations
#include <stack>
const int LENGTH = 15;
char *temp = new char[LENGTH];
stack<string> constStack;
How can I provide a proper formating to string?
Simple - provide a format string:
sprintf(temp, "%s", constStack.top().c_str());
But much, much better:
string temp = constStack.top();
You are telling me in your comment that the problem is not so much the warning as the fact that your code doesn't do what you expect it to.
The solution to this and other, similar problems is to get rid of the strong C influence in your C++ code. Specifically, don't use raw dynamically allocated char arrays or sprintf. Use std::string instead.
In this case, you are using sprintf very incorrectly. Have you ever seen its signature? It goes like this:
sprintf(char *str, char const *format, ...)
str is the output of the operation. format describes what the output should be. The rest are the format arguments, which must by pure convention match what's described in format.
Now this "rest", written as ..., means that you can pass any number of arguments, even zero. And this is why your code even compiles (delivering a nice example for why ... is a dangerous feature, by the way).
In your code, the output string is, possibly incorrectly, your temp string. And the format to describe the output is, almost certainly incorrectly, what happens to sit on top of your stack.
Is this just about assigning one string to another, using sprintf simply because it more or less can do that as a very special case of what its feature set offers? There's no need for such hacks, as C++ has string assignment out of the box with std::string:
std::string temp = constStack.top();
Notice that this also eliminates the need to know the length of the string in advance.
If, for some reason, you really need formatting (but your question doesn't really show any need for it), then learn more about string streams as an alternative solution to format strings.
As the warning indicates it is issued as a result of the -Wformat-security option; you could simply disable the warning by removing the option; but it would be perhaps unwise.
The security issue is perhaps theoretical unless your code is to be widely distributed. Of perhaps more immediate concern is the possibility of your code crashing or behaving abnormally.
The problem is that the string is variable, and may at runtime contain formatting characters that cause it to attempt to read non-existent arguments. If for example the string is received from user input and the user entered "%s" it would attempt to read a string from some somewhere on the stack. That would at best place junk in temp, but worse if the memory read happened not to contain a nul character in the first 15 bytes, it would overrun temp, and corrupt the heap (in this case). Heap corruptions are probably worse than stack corruptions - the latent bug can remain unnoticed in your code for a long time only to start crashing after some unrelated change; and if it does crash, it is unlikely to be in any proximity to the cause.

When to use std::string vs char*? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ char* vs std::string
I'm new to C++ coming from C# but I really do like C++ much better.
I have an abstract class that defines two constant strings (not static). And I wondered if a const char* would be a better choice. I'm still getting the hang of the C++ standards, but I just figured that there really isn't any reason why I would need to use std::string in this particular case (no appending or editing the string, just writing to the console via printf).
Should I stick to std::string in every case?
Should I stick to std::string in every case?
Yes.
Except perhaps for a few edge cases where you writing a high performance multi-threaded logging lib and you really need to know when a memory allocation is going to take place, or perhaps in fiddling with individual bits in a packet header in some low level protocol/driver.
The problem is that you start with a simple char and then you need to print it, so you use printf(), then perhaps a sprintf() to parse it because std::stream would be a pain for just one int to string. And you end up with an unsafe and unmaintainable mix oc c/c++
I would stick to using std::string instead of const char*, simply because most of the built-in C++ libraries work with strings and not character arrays. std::string has a lot of built-in methods and facilities that give the programmer a lot of power when manipulating strings.
Should I stick to std::string in every case?
There are cases where std::string isn't needed and just a plain char const* will do. However you do get other functionality besides manipulation, you also get to do comparison with other strings and char arrays, and all the standard algorithms to operate on them.
I would say go with std::string by default (for members and variables), and then only change if you happen to see that is the cause of a performance drop (which it won't).
Use std::string when you need to store a value.
Use const char * when you want maximum flexibility, as almost everything can be easily converted to or from one.
This like comparing Apples to Oranges. std::string is a container class while char* is just a pointer to a character sequence.
It really all depends on what you want to do with the string.
Std::string on the other hand can give you a quick access for simple string calculation and manipulation function. Most of those are simple string manipulation functions, nothing fancy really.
So it basically depends on your needs and how your functions are declared. The only advantage for std::string over a char pointer is that it doesnt require a specific lenghth decleration.

what is use of C_str() function in C/C++

Can anybody tell me what is the use of c_str() function in C/C++?.
In which case it is necessary to use it?.
When you want to use your string with C-functions
string s = "hello";
printf( "your string:%s", s.c_str() );
It is a C++ thing, not a C one.
A common use of c_str (from std::string) is precisely to convert a C++ std::string to a const char* C string, which is required by many many low level C functions (e.g. Posix system calls like stat, etc).
Generates a null-terminated sequence of characters (c-string) with the same content as the string object and returns it as a pointer to an array of characters.
There is a good example of its use here: http://www.cplusplus.com/reference/string/string/c_str/
I presume you're asking about string::c_str()? It's a method that returns a C string representation of the string object. You might need a C string representation to call an OS API, for example.

C++: Is it safe to move a jpeg around in memory using a std::string?

I have an external_jpeg_func() that takes jpeg data in a char array to do stuff with it. I am unable to modify this function. In order to provide it the char array, I do something like the following:
//what the funcs take as inputs
std::string my_get_jpeg();
void external_jpeg_func(const char* buf, unsigned int size);
int main ()
{
std::string myString = my_get_jpeg();
external_jpeg_func(myString.data(), myString.length() );
}
My question is: Is it safe to use a string to transport the char array around? Does jpeg (or perhaps any binary file format) be at risk of running into characters like '\0' and cause data loss?
My recommendation would be to use std::vector<char>, instead of std::string, in this case; the danger with std::string is that it provides a c_str() function and most developers assume that the contents of a std::string are NUL-terminated, even though std::string provides a size() function that can return a different value than what you would get by stopping at NUL. That said, as long as you are careful to always use the constructor that takes a size parameter, and you are careful not to pass the .c_str() to anything, then there is no problem with using a string here.
While there is no technical advantage to using a std::vector<char> over a std::string, I feel that it does a better job of communicating to other developers that the content is to be interpreted as an arbitrary byte sequence rather than NUL-terminated textual content. Therefore, I would choose the former for this added readability. That said, I have worked with plenty of code that uses std::string for storing arbitrary bytes. In fact, the C++ proto compiler generates such code (though, I should add, that I don't think this was a good choice for the readability reasons that I mentioned).
std::string does not treat null characters specially, unless you don't give it an explicit string length. So your code will work fine.
Although, in C++03, strings are technically not required to be stored in contiguous memory. Just about every std::string implementation you will find will in fact store them that way, but it is not technically required. C++11 rectifies this.
So, I would suggest you use a std::vector<char> in this case. std::string doesn't buy you anything over a std::vector<char>, and it's more explicit that this is an array of characters and not a possibly printable string.
I think it is better to use char array char[] or std::vector<char>. This is standard way to keep images. Of course, binary file may contain 0 characters.