I’m having some issues with std::cout, std::stringstream, and std::string.c_str(). Mainly, it seems that there’s stuff that’s getting caught in a buffer somewhere, and I’m not sure how to fix the problem.
If you don’t like reading code in StackOverflow, here are the relevant links to my github:
The TLString class, the Test class, and the unit test — and you can skip to the end where I state my more concise question.
In my unit test, I have the following code:
Test <std::string> strtest; // A unit test object expecting strings.
Test <const char*> chtest; // A unit test object expecting const char*s
// ...
TurnLeft::Utils::TLString str3("Exterminate.");
// ...
/* Basically, name() and expect() will use the passed arg.
* in the output in order to
* display output such as the following:
* str(): expecting 'Exterminate.' | Actual 'Exterminate.' => PASS
*/
strtest.name("str()").expect("Exterminate.").test( str3.str() );
/* To try and determine where the corruption was occuring, I did a
* simple cout here, and got what should be the expected result of
* the next test,
* meaning that the actual test should be succeeding.
*/
std::cout << str3.c_str() << std::endl //outputs Exterminate. normally.
/* But when I try to invoke that same method (c_str()) within the test
* object, it simply copies the argument passed in for name().
*/
chtest.name("c_str()").expect("Exterminate.").test( str3.c_str() );
// Should output 'Exterminate.' as in the saatement before, but instead
// outputs 'c_str()'.
Here’s the code for the Test class:
namespace unittest{
static std::string status[2] = {"FAIL", "PASS"};
template <class ExpectedResult>
class Test
{
private:
ExpectedResult expected;
ExpectedResult actual;
std::string testName;
public:
Test();
Test <ExpectedResult>& expect (ExpectedResult value);
Test <ExpectedResult>& name (std::string);
void test (ExpectedResult value);
};
template <class ExpectedResult> Test <ExpectedResult>&
Test<ExpectedResult>::expect(ExpectedResult value)
{
expected = value;
return *this;
}
template <class ExpectedResult>
Test <ExpectedResult>&
Test<ExpectedResult>::name(std::string aName)
{
testName = aName;
return *this;
}
template <class ExpectedResult>
void Test<ExpectedResult>::test(ExpectedResult value)
{
actual = value;
std::cout << testName << ": ";
std::cout << "Expecting: " << expected << " | ";
std::cout << "Actual: " << actual;
std::cout << " => " << status[actual==expected] << std::endl;
}
The TLString class is one that I’m writing that will give some more fluid operation to strings in C++ (for example, concatenation). It uses a stringstream in order to handle these operations. The TLStream::c_str() method is really just doing this: return stream.str().c_str();
So, I’m really confused about how actual is being assigned the value of testName. I’m not sure where the conflict is occurring, given that the only time those to variables come close to interacting is when they are both output to to the CLI, and even moreso as in this case, those two are different datatypes.
I’ve written in the c_str() functionality because, quite simply, you just never know when some third-party library is going to rely on C strings instead of C++ strings, and saw no reason to limit my class. Even within std::ios, you need to use c strings for some things.
Any help would be greatly appreciated.
Thanks!
std::stringstream.str()returns a temporary object of typestd::string. This temporary goes out of scope whenTLStream::c_str()returns, leaving the returnedchar const*pointer pointing to freed memory.