-1

In RHEL linux, using std::string variable assigned with ""(empty string value) is giving junk values

For example as in the below code

std::string str = "";

printf("%s",str.c_str());

I have one more code sample

int main()
{
string str = "";
printf("Str = %s\n" ,str.c_str());

string strTemp;
char * pcTRMP = new char [10];

//sprintf(pcTRMP,"%d" ,7);
sprintf((char*)strTemp.c_str() ,"%d" ,7);
printf("Str = %s\n" ,str.c_str());

sprintf((char*)strTemp.c_str() ,"%d" ,8);
printf("Str = %s\n" ,str.c_str());

return 0;
}

The result is Str = 7 Str = 8

where there is no assignment to str variable.

We checked in so many places in internet. I am hoping that someone can help me to resolve this issue.

The same code is working in older versions of RHEL Linux.

Neo
  • 21
  • 4
  • 1
    You can not write into `strTemp.c_str()` and expect well-defined behaviour. The cast to `(char*)` is casting away `const`, that should tip you off that what you are venturing into undefined behaviour. – Magnus Hoff Nov 04 '14 at 15:08
  • What do you mean by "giving junk values" in the first example? What is the unexpected output you are presumably getting? – Magnus Hoff Nov 04 '14 at 15:10
  • I expect str value should be an empty string. But it is giving 7 in the second example. and some junk number in first example. – Neo Nov 04 '14 at 15:20
  • The first example should really give empty output. Anything else is a bug. I cannot reproduce your observed result, though. Does this program exhibit the behaviour you see on your machine? http://coliru.stacked-crooked.com/a/385031d05514cb2d – Magnus Hoff Nov 04 '14 at 15:27

2 Answers2

2

It is illegal to write into the pointer returned by std::string::c_str(). The documentation for std::string indicates explicitely that this results in undefined behavior. This pointer is originally of type const char *, specifically to express this limitation.

Regarding the results displayed by your program, I guess both strings point to the same empty string buffer (some internal const char empty[] = ""), so that a write to one results in changing the value of all empty strings.

If you really need to use sprintf instead of std::stringstream, you can use char vectors instead of strings:

std::vector<char> buf(10);
sprintf(buf.data(), "%d" ,7);
std::string result = buf.data();
slaphappy
  • 6,894
  • 3
  • 34
  • 59
  • @msk "Is working"? There is no defined way it *should* work. Your code is undefined according to the language standard. You should really fix that :) – Magnus Hoff Nov 04 '14 at 15:28
  • See my point is not to use sprint. When I am changing variable strTemp, variable str is changing. Is there any solution for this. – Neo Nov 04 '14 at 15:31
  • @msk: Yes, the program appears to be working; this is what "undefined" means. However, you have a dangerous buffer overrun in the windows version (where strings work differently), which may crash anytime in the future. – slaphappy Nov 04 '14 at 15:32
  • @msk There are several ways to modify a string, for instance, via the index operator (`[]`), via an external buffer (see my example with vector). Just don't use c_str as it is read-only. – slaphappy Nov 04 '14 at 15:39
  • msk: Ignoring that all of this is still wrong (using sprintf() to write into the memory behind the internal string pointer?), I think by "works" you might be referring to the fact that (at least on your system), modifying the memory behind the second string also affects the first string? That might be due to the implementation of std::string. But if the rest of the code does similarly bad things, the implementation of std::string should be the last thing to worry about (no offense). – basic6 Nov 04 '14 at 16:23
0

You are messing with internal string pointers and, as a result, experiencing undefined behavior.

An std::string object is a C++ string object. You create such an object (str), then create a second one (strTemp), fetch a const char * from the second one - then you try to write integers into that char array. Of course, the compiler knows that this is wrong (const) and will complain:

invalid conversion from const char* to char*

So you forcefully ignore this error by casting the const away. Now, after forcefully ignoring an error, unexpected things happen.

This has nothing to do with the platform, at least in general. As it is undefined behavior, the symptoms may however differ depending on what platform you use. I'm thinking that both string objects (both being empty) share the same memory location (at least as long as they're identical) (on the platform that was used), so overwriting the memory behind the pointer returned by the second string also affects the first string object. If you assign different values to the strings, the sprintf() won't (depending on platform) affect the other string anymore (example) - of course that's still wrong.

Read up on C++/C (C++ objects, C pointers and the meaning of const) and specifically the documentation of std::string.

Edit:

The op appears to be focused on the platform, so I'll repeat the obvious here. Writing to (the const representation of) variable a (strTemp) and then expecting that data to be in variable b (str) is bogus. You are overwriting memory that you don't own and, concidentally, overwriting the internal memory of another variable (str). Under certain circumstances, that data just happens to end up in ANOTHER variable. This is just completely and utterly broken.
I really hope this is just a test program or something - and not a productive application.

And don't mix C/C++ like that. In C++, you can still create a char* (big enough) and use functions like sprintf() that expect such a C string to write to it - if there's a good reason. Otherwise, just write proper C++.

For example, if converting an int to a C++ string is your actual problem, here is an example:

#include <iostream>
#include <sstream>

//...
std::string str;
int number = 7;
ostringstream oss;
oss << number;
str = oss.str();

Some people write macros for that. There are other solutions as well (I think boost has something to offer, so does C++0x).

Community
  • 1
  • 1
basic6
  • 3,643
  • 3
  • 42
  • 47
  • Please do not think that this is the first time we are using Linux. The same code is working in older versions of RHEL Linux. – Neo Nov 05 '14 at 05:13
  • msk I don't know why you keep repeating that, undefined behavior cannot "work" (by definition) no matter how often you say it. If you think that your question has not been answered yet, please rephrase it. But unless you explain why you expect broken code to work, there's nothing I can do for you. – basic6 Nov 05 '14 at 09:07