C++ Odd behaviour with ostringstream - c++

Is there any explanation in the standard for the below behavior?
The following code:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
ostringstream os1;
ostringstream os2;
os1 << 1 << " " << 2;
os2 << 1 << " " << 2 << " " << 3;
const char *p = os1.str().c_str();
cout << os2.str() << endl;
cout << p << endl;
return 0;
}
displays the output:
1 2 3
1 2 3
However, I would expect it to display:
1 2 3
1 2
It looks like os1 object is somehow influenced by os2, if I remove the os2.str() call, example behaves correctly.
I have tried the example if Solaris Studio 12.2 and G++ 4.8.1 and both behave in the same way.
Thanks for your help!

const char *p = os1.str().c_str();
Here is the problem, in the above line.
os1.str() returns a temporary string object by copying the internal string buffer. And you're taking .c_str() of the temporary object, which gets destroyed at the end of the full expression. The result is, p points to the destroyed object when you take it to print using std::cout.
That is, your program invokes undefined behavior (UB).
Try this:
auto s = os1.str();
const char *p = s.c_str(); //s is not a temporary object anymore!
Now it gives correct output (and this is your code — luckily even coliru gives the same output as you observed on your machine. Note that this output is not guaranteed though precisely because the code invokes UB.).

I think the issue has to do with retaining the pointer returned by c_str().
ostringstream::str() is returning a temporary string object, and you are saving a pointer to it's internal char array. But once that line has executed, the returned string object will be deleted. So your pointer will be invalid.
If you want to keep a c_str pointer around for some reason, you would need to also keep a copy of the string:
string s = os1.str();
const char *p = s.c_str();
cout << os2.str() << endl;
cout << p << endl;

The answer to this question is here:
stringstream, string, and char* conversion confusion
stringstream.str() returns a temporary string object that's destroyed at the end of the full expression. If you get a pointer to a C string from that (stringstream.str().c_str()), it will point to a string which is deleted where the statement ends.

Related

C++ c_str of std::string returns empty

So, I'm running into an issue with the following code whereby the result of std::cout << cstr << std::endl is the single character
PyObject * CKKSwrapper::SerializeContext() {
std::string s; // 1
std::ostringstream os(s); // 2
Serial::Serialize(m_cc, os, SerType::BINARY); // 3
const std::string string_repr = os.str(); // 4
std::cout << string_repr << std::endl; // 5
char *cstr = new char[string_repr.length() + 1]; // 6
std::strcpy(cstr, string_repr.c_str()); // 7
std::cout << "******************************************************" << std::endl; // 8
std::cout << string_repr << std::endl; // 9
std::cout << "******************************************************" << std::endl; // 10
std::cout << cstr << std::endl; // 11
auto resp = PyBytes_FromString(cstr); // 12
return resp;
}
Checking the std::cout result on line 5 looks good and is non-empty.
# � �4 lbcrypto::LPCryptoParametersCKKSlbcrypto::DCRTPoly � # �
^ the first few characters (not sure if that helps)
Later, I create a char array and copy over the c_str to it which (I think) avoids the issue of a temporary result as was discussed https://stackoverflow.com/a/39006531/3532564
Don't attempt to store the pointer returned by c_str(). If you need that string as a C-string for an extended period of time, allocate memory buffer for it yourself and copy the result of c_str() to that buffer.
I also found https://stackoverflow.com/a/35981001/3532564 which made me wonder if my string_repr object was being destroyed so I did a std::cout on line 9 and it looks good also.
Can anyone help me? I'm really not sure where the issue stems from. Unfortunately, I need to pass a char * [] to PyBytes_FromString despite what the name might make one think
Presumably the string contains one or more nul characters, resulting in strcpy() not copying all of the bytes. You also have a memory leak from not freeing cstr before you return from the function.
You can avoid both problems by bypassing the unnecessary string array and calling PyBytes_FromStringAndSize:
return PyBytes_FromStringAndSize(string_repr.c_str(), string_repr.size());

How am I receiving the following output when (incorrectly) dereferencing a pointer to a pointer?

This is not so much a question that I need solving, it's more a case of I made a mistake which resulted in weird output, and I'm curious what's going on.
So if point1 is a pointer to the char "var", and point2 is a pointer to the pointer point1, to correctly dereference point2 as follows:
cout << **point2 << endl;
Which would ouput "y" as expected.
However, if I incorrectly dereference the pointer, as follows:
cout << *point2 << endl;
Then the output would include any subsequent variables declared after the initial variable var.
For example, in the code below, var2 would also be included, for an ouput of "yn", and further variables such as
char var3 = 'a';
char var4 = 'b';
Also seem to be included for an ouput of "ynab".
I think I understand how it's happening, and outputting the memory addresses of each of the variables through a method such as:
cout << (void *) &var <<endl;
Which confirms that each variable is adjacent in memory, however I'm unsure why it is happening.
Why does improperly dereferencing a pointer to a pointer seem to return successive variables?
Code:
#include <stdio.h>
#include <iostream>
using namespace std;
char var = 'y';
char var2 = 'n';
//Declare point1 as a pointer to a char
char* point1 = &var;
//Declare point2 as pointer to pointer to char
char** point2 = &point1;
int main(int argc, char **argv)
{
cout << "Dereference point1: " << *point1 << endl;
cout << "Dereference point2: " << **point2 << endl;
cout << "Bad dereference of point2: " << *point2 << endl;
cout << "Var: " << var << endl;
return 0;
}
The expression *point2 is of type char * which is treated as a string. If it's not really a string then you have undefined behavior and that's really the end of the story.
In reality what happens is that the output operator << reads consecutive bytes from memory until it hits a zero (the "string terminator"). In your case the compiler have put the storage for the variables next to each other, that's why you see both being output in the "string".
C++ thinks that the pointer to char is the beginning of a string. So it tries to continue printing until it finds a NULL value.

Passing string 'by value' change in local value reflect in original value

Why is the change of my local variable's value getting reflected into original variable? I am passing it by value in C++.
#include <string>
#include <iostream>
void test(std::string a)
{
char *buff = (char *)a.c_str();
buff[2] = 'x';
std::cout << "In function: " << a;
}
int main()
{
std::string s = "Hello World";
std::cout << "Before : "<< s << "\n" ;
test(s);
std::cout << "\n" << "After : " << s << std::endl;
return 0;
}
Output:
Before : Hello World
In function: Hexlo World
After : Hexlo World
As soon as you wrote
buff[2] = 'x';
and compiled your code all bets were off. Per [string.accessors]
const charT* c_str() const noexcept;
Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
Complexity: constant time.
Requires: The program shall not alter any of the values stored in the character array.
emphasis mine
Since you are not allowed to modify the characters that the pointer points to but you do, you have undefined behavior. The compiler at this point is allowed to do pretty much whatever it wants. Trying to figure out why it did what it did is meaningless as any other compiler might not do this.
The moral of the story is do not cast const away unless you are really sure that you know what you are doing and if you do you need to, then document the code to show you know what you are doing.
Your std::string implementation uses reference counting and makes a deep copy only if you modify the string via its operator[] (or some other method). Casting the const char* return value of c_str() to char* will lead to undefined behavior.
I believe since C++11 std::string must not do reference counting anymore, so switching to C++11 might be enough to make your code work (Edit: I did not actually check that before, and it seems my assumption was wrong).
To be on the safe side, consider looking for a string implementation that guarantees deep copying (or implement one yourself).
#include <cstring>
#include <string>
#include <iostream>
void test(std::string a)
{
// modification trough valid std::string API
a[2] = 'x';
const char *buff = a.c_str(); // only const char* is available from API
std::cout << "In function: " << a << " | Trough pointer: " << buff;
// extraction to writeable char[] buffer
char writeableBuff[100];
// unsafe, possible attack trough buffer overflow, don't use in real code
strcpy(writeableBuff, a.c_str());
writeableBuff[3] = 'y';
std::cout << "\n" << "In writeable buffer: " << writeableBuff;
}
int main()
{
std::string s = "Hello World";
std::cout << "Before : "<< s << "\n" ;
test(s);
std::cout << "\n" << "After : " << s << std::endl;
return 0;
}
Output:
Before : Hello World
In function: Hexlo World | Trough pointer: Hexlo World
In writeable buffer: Hexyo World
After : Hello World

With a string longer than 10 letters, char* changes without any apparent reason. Why?

In step 2 I change only the value of name_C. Why does name_B also change?
Here is the code:
#include <cstdlib>
#include <dirent.h>
#include <iostream>
#include <fstream>
#include <direct.h>
using namespace std;
int main(int argc, char *argv[])
{
// step 1
char *name_A;
char *name_B;
char *name_C;
string str_L = "hello";
string str_M = "stringVar_A"; ;
name_A = (char *) str_M.c_str();
name_B = (char *) (str_L + "-car-" + str_M).c_str();
name_C = (char *) str_L.c_str();
cout << " name_A= " << name_A << endl;
cout << " name_B= " << name_B << endl;
cout << " name_C= " << name_C << endl << endl << endl;
// step 2
string str_N = "myStringMyString"; // (in my real code, i can't put this line in step 1)
string str_R = "ABCDEFGHI" + str_N; // (in my real code, i can't put this line in step 1)
name_C = (char *)str_R.c_str(); // change only name_C
cout << " name_A= " << name_A << endl;
cout << " name_B= " << name_B << endl; // changed, why?
cout << " name_C= " << name_C << endl; // changed, ok.
system("PAUSE");
return EXIT_SUCCESS;
};
Here the output:
(step 1:)
name_A= stringVar_A
name_B= hello-car-stringVar_A
name_C= hello
(step 2:)
name_A= stringVar_A
name_B= ABCDEFGHImyStringMyString
name_C= ABCDEFGHImyStringMyString
With:
string str_N = "myString"; // in step 2...
name_B does not change.
Why does name_B change if str_N is longer than 10 letters?
Can someone help me understand this behavior?
The pointer returned by a call to c_str is only valid for as long as the corresponding std::string stays in scope and is unmodified.
The behaviour in accessing it beyond that is undefined.
For example, (str_L + "-car-" + str_M).c_str(); is returning you the c_str of an anonymous temporary. It will be immediately invalid after the assignment. In your case, name_B is invalidated.
Also, don't cast away the const char* return of c_str(). It's const for a very good reason: you should not attempt to modify the string contents through that pointer.
You are causing undefined behaviour.
name_B = (char *) (str_L + "-car-" + str_M).c_str();
you create a temoprary string from the result of std::string::operator + , extract the C-character array out of it, but then no-one really cathes the temporary string.
when a temporary is not caught by const reference - it is destroyed right away. the string destructor de-allocates the inner character array and invalidates name_B.
so, this is undefined behaviour since you try to work with memory address that is no longer valid.
std::string::c_str() returns a pointer to an internal buffer of a std::string with the guarantee that:
it points to a NUL-terminated string;
the range [c_str(); c_str() + size()] is valid.
In your case, name_B points to an internal buffer of a temporary object name_B = (str_L + "-car-" + str_M).c_str(); which will lead to an Undefined Behaviour when you'll try to use it.
When you make some modifications on your stack (you define two new std::strings), you probably alter the stack place where your name_B points to (since the memory reserved by your temporary has been freed).
If you really have to get old style C-strings from your std::strings, make sure:
The pointer retrieved from std::string::c_str() is no longer used when the std::string is modified or destroyed,
hence you don't call std::string::c_str() from a temporary.

C++ snippet OK with MSVC but not with g++

I'm new to C++ and I try to adapt a program snippet which generates "weak compositions" or Multisets found here on stackoverflow but I run - to be quite frank - since hours into problems.
First of all, the program runs without any complaint under MSVC - but not on gcc.
The point is, that I have read many articles like this one here on stackoverflow, about the different behaviour of gcc and msvc and I have understood, that msvc is a bit more "liberal" in dealing with this situation and gcc is more "strict". I have also understood, that one should "not bind a non-const reference to a temporary (internal) variable."
But I am sorry, I can not fix it and get this program to work under gcc - again since hours.
And - if possible - a second question: I have to introduce a global variable
total, which is said to be "evil", although it works well. I need this value of total, however I could not find a solution with a non-global scope.
Thank you all very much for your assistance.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int total = 0;
string & ListMultisets(unsigned au4Boxes, unsigned au4Balls, string & strOut = string(), string strBuild = string()) {
unsigned au4;
if (au4Boxes > 1) for (au4 = 0; au4 <= au4Balls; au4++)
{
stringstream ss;
ss << strBuild << (strBuild.size() == 0 ? "" : ",") << au4Balls - au4;
ListMultisets(au4Boxes - 1, au4, strOut, ss.str());
}
else
{
stringstream ss;
ss << mycount << ".\t" << "(" << strBuild << (strBuild.size() == 0 ? "" : ",") << au4Balls << ")\n";
strOut += ss.str();
total++;
}
return strOut;
}
int main() {
cout << endl << ListMultisets(5,3) << endl;
cout << "Total: " << total << " weak compositions." << endl;
return 0;
}
C++ demands that a reference parameter to an unnamed temporary (like string()) must either be a const reference or an r-value reference.
Either of those reference types will protect you from modifying a variable that you don't realize is going to be destroyed within the current expression.
Depending on your needs, it could would to make it a value parameter:
string ListMultisets( ... string strOut = string() ... ) {
or it could would to make it a function-local variable:
string ListMultisets(...) {
string strOut;
In your example program, either change would work.
Remove the default value for the strOut parameter.
Create a string in main and pass it to the function.
Change the return type of the function to be int.
Make total a local variable ListMultisets(). Return total rather than strOut (you are returning the string value strOut as a reference parameter.)
The signature of the new ListMultisets will look like:
int ListMultisets(unsigned au4Boxes, unsigned au4Balls, string & strOut)
I'll let you figure out the implementation. It will either be easy or educational.
Your new main function will look like:
int main() {
string result;
int total = ListMultisets(5,3, result);
cout << endl << result << endl;
cout << "Total: " << total << " weak compositions." << endl;
return 0;
}