I tried the following code:
#include <iostream>
using std::cout;
using std::ostream;
class X
{
public:
friend ostream& operator<<(ostream &os, const X& obj)
{
cout << "hehe"; // comment this and infinite loop is gone
return (os << obj);
}
};
int main()
{
X x;
cout << x;
return 0;
}
When I compile & run this, it's as expected; an infinite loop. If I remove the cout statement inside the friend function, the recursion doesn't happen. Why is it so?
Optimizer decides all your remaining activity has no effect and optimizes it away.
Whether it's right or wrong is a different matter.
In particular:
X x;
creates empty object "x"
cout << x;
calls:
return (os << obj);
which is appending empty object; the compiler notices 'os' hasn't grown any since the last call and shows no promise doing so any further (and nothing else happens) so it decides the whole business is redundant and can be truncated at this point.
In case you call
cout << "hehe"; // comment this and infinite loop is gone
there is some extra activity so the optimizer doesn't remove the following call.
I guess if you initialized x with anything non-empty, or performed any non-null activity other than cout << "hehe";, you'd have recursion running just the same.
In both cases (with and without writing "hehe") Visual Studio 2005 gives the following warning:
warning C4717: 'operator<<' : recursive on all control paths, function will cause runtime stack overflow
In both cases it compiles and in both cases it gives a stack overflow.
However, without the "hehe" the stack overflow occurs a bit sooner.
Related
I ran into a nasty bug in some of my code. Here's the simplified version:
#include <iostream>
class A
{
public:
std::string s;
void run(const std::string& x)
{
// do some "read-only" stuff with "x"
std::cout << "x = " << x << std::endl;
// Since I passed X as a const referece, I expected string never to change
// but actually, it does get changed by clear() function
clear();
// trying to do something else with "x",
// but now it has a different value although I declared it as
// "const". This killed the code logic.
std::cout << "x = " << x << std::endl;
// is there some way to detect possible change of X here during compile-time?
}
void clear()
{
// in my actual code, this doesn't even happen here, but 3 levels deep on some other code that gets called
s.clear();
}
};
int main()
{
A a;
a.s = "test";
a.run(a.s);
return 0;
}
Basically, the code that calls a.run() use to be used for all kinds of strings in the past and at one point, I needed the exact value that object "a.s" had, so I just put a.s in there and then some time later noticed program behaving weird. I tracked it down to this.
Now, I understand why this is happening, but it looks like one of those really hard to trace and detect bugs. You see the parameter declared as const & and suddenly it's value changes.
Is there some way to detect this during compile-time? I'm using CLang and MSVC.
Thanks.
Is there some way to detect this during compile-time?
I don't think so. There is nothing inherently wrong about modifying a member variable that is referred by a const reference, so there is no reason for the compiler to warn about it. The compiler cannot read your mind to find out what your expectations are.
There are some usages where such wrong assumption could result in definite bugs such as undefined behaviour that could be diagnosed if identified. I suspect that identifying such cases in general would be quite expensive computationally, so I wouldn't rely on it.
Redesigning the interface could make that situation impossible For example following:
struct wrapper {
std::string str;
};
void run(const wrapper& x);
x.str will not alias the member because the member is not inside a wrapper.
The main problem is that when typing cout<<f1; alone it worked as well as f1++; alone but when attempting to enter cout<<f1++; together it shows that error knowing that when making the post increment it is returning a fraction object.
ostream& operator <<(ostream& output, fraction& fraction1)
{
output << "[" << fraction1.num << "/" << fraction1.denom << "]" << endl;
return output;
}
fraction fraction::operator ++(int)
{
fraction temp = *this;
++(this->num);
++(this->denom);
return temp;
}
int main()
{
fraction f1;
cout << f1;
f1++;
cout << f1++ << endl; // Results in compiler error
return 0;
}
The compiler error is: no operator "<<" matches these operands
Reasoning by analogy, consider this setup:
void doSomething(int& x) {
x = 137;
}
int main() {
doSomething(42); // Oops!
}
This code won’t compile because there’s an error in the indicated line. The function doSomething expects an int&, which you can think of as meaning “please give me an actual int variable or int object somewhere that I can change.” But 42 isn’t an int variable - it’s a pure value, hence the error.
Now, suppose you change main to this:
int main() {
int var = 42;
doSomething(var++); // Oops!
The expression var++ means “increment var, then hand back the value it used to have.” That means that we’re still passing the pure value 42 into the function, and since the function wants objects and not values, this won’t compile.
However, you can make this version of main work by changing doSomething to take in a const int&:
void doSomething(const int& x) {
// do something other than change x
}
This code works just fine due to how C++ defines const references. Unlike a regular reference, which means “I’d like to be able to change this object,” a const reference works fine when you pass in a pure value, since the const bit means “I promise not to actually change anything here.”
Now, look at your code. It’s basically the same idea as what’s shown above: you have a function named operator<< whose second parameter is a fraction&. That means that you can’t pass in the result of the ++ operator. And the fix is the same - just change the second parameter to use a const reference.
Hope this helps!
I have create a program to overload << operator for my class.
I have a doubt about the return type of the overloaded method.
When i am returning the out from the overloaded operator function the program is working fine.
But when i am not returning any thing from the function the program crashing under one condition.
In many C++ resource i have read that the return type is necessary to print operators in cascading .
Condition 1 : Passing
When i am using statement
// cout<<"\n"<<mv1<<mv2<<mv3;
Every thing is working fine. Passing without return from overloaded function.
Condition 2:Failing
When i am using statemtent
cout<<"\n"<
This i know that return was not there so the program crashed at runtime.
But the question is what made program run in Condition 1 . Even without the return statement was not present in the overloading function.
Program below
I have create a program to overload << operator for my class.
I have a doubt about the return type of the overloaded method.
When i am returning the out from the overloaded operator function the program is working fine.
But when i am not returning any thing from the function the program crashing under one condition.
In many C++ resource i have read that the return type is necessary to print operators in cascading .
Condition 1 : Passing
When i am using statement
// cout<<"\n"<<mv1<<mv2<<mv3;
Every thing is working fine. Passing without return from overloaded function.
Condition 2:Failing
When i am using statemtent
cout<<"\n"<
This i know that return was not there so the program crashed at runtime.
But the question is what made program run in Condition 1 . Even without the return statement was not present in the overloading function.
Program below
#include <iostream>
#include <stdio.h>
using namespace std;
class myvar{
private:
int var_x,var_y;
public:
friend ostream& operator<<(ostream &out,myvar n);
void setvalue(int x,int y)
{
var_x = x ;
var_y = y ;
}
};
ostream& operator<<(ostream &out,myvar n)
{
cout<<"("<<n.var_x<<","<<n.var_y<<")";
//return out;
}
int main()
{
myvar mv1,mv2,mv3;
mv1.setvalue(10,20);
mv2.setvalue(30,40);
mv3.setvalue(50,60);
//Working
// cout<<"\n"<<mv1<<mv2<<mv3;
//Not Working
// cout<<"\n"<<mv1<<mv2<<mv3<<"Hello"<<1243<<11.5;
}
This code has Undefined Behavior.
This is very bad. Usually it means that a crash will happen (but technically anything can happen).
ostream& operator<<(ostream &out,myvar n)
{
out<<"("<<n.var_x<<","<<n.var_y<<")"; // fixed cout to out.
//return out;
}
This is because you specify a return type in the function signature.
ostream& operator<<(ostream &out,myvar n)
^^^^^^^^
If your function does not contain a return keyword then your code is invalid. So for the function as defined (with the commented out return) your program will most likely crash.
If you change your code to:
void operator<<(ostream &out,myvar n)
{
out<<"("<<n.var_x<<","<<n.var_y<<")";
}
Now it will compile (be valid) and work.
But the consequence is you can not chain stream operations together.
myvar x;
// Set some value in x
// This will work fine.
std::cout << x;
// But this will fail to compile.
std::cout << x << " Another Thing";
Because the first call to operator<< returns a void the second call to operator<< does not know what to do.
So your best bet is to return the stream to allow chaining.
ostream& operator<<(ostream &out,myvar n)
{
out<<"("<<n.var_x<<","<<n.var_y<<")";
return out;
}
PS: Some space characters would be really nice to aid readability.
// This is easier to read for a human.
std::ostream& operator<<(std::ostream &out, myvar n)
{
out << "(" << n.var_x << "," << n.var_y << ")";
return out;
}
Yes, you always return the passed in ostream and probably want to pass in a const reference to the value you want outputed:
ostream& operator<<(ostream &out, const myvar& n)
{
out << "(" << n.var_x << "," << n.var_y << ")";
return out;
}
My biggest doubt is that why chaining of << in following statement
is working even without the return of out from overloaded function.
cout<<"\n"<<mv1<<mv2<<mv3;
I'm working with some multithreaded code for a game project, and got a bit tired of sorting through the stdout vomit created by two threads using cout for debuging messages at the same time. I did some research and stared at a wall for an hour or two before coming up with "something". The following code uses SFML for time keeping and threading. SFML mutexes are just wrapped critical sections in windows.
Header:
#include <SFML\System.hpp>
#include <iostream>
class OutputStreamHack
{
public:
OutputStreamHack();
~OutputStreamHack();
ostream& outputHijack(ostream &os);
private:
sf::Clock myRunTime;
sf::Mutex myMutex;
};
static OutputStream OUTHACK;
ostream& operator<<(ostream& os, const OutputStreamHack& inputValue);
Implementation:
#include <SFML\System.hpp>
#include <iostream>
#include "OutputStreamHack.h"
using namespace std;
OutputStreamHack::OutputStreamHack()
{
myMutex.Unlock();
myRunTime.Reset();
}
OutputStreamHack::~OutputStreamHack()
{
myMutex.Unlock();
myRunTime.Reset();
}
ostream& OutputStreamHack::outputHijack(ostream &os)
{
sf::Lock lock(myMutex);
os<<"<"<<myRunTime.GetElapsedTime()<<","<<GetCurrentThreadId()<<"> "<<flush;
return os;
}
ostream& operator<<(ostream& os, const OutputStreamHack& inputValue)
{
OUTHACK.outputHijack(os);
return os;
}
Usage:
cout<<OUTHACK<<val1<<val2<<val3....<<endl;
Ok, so the way this works is through an overloaded insertion operator that imposes thread safety by locking an iterator in a static object, then flushing the buffer. If I understand the process correctly (I am mostly a self taught programmer), cout processes elements of its insertion chain from the end to the beginning, passing an ostream variable down the chain for each element to be prepended to the stream. Once it reaches the OUTHACK element, the overloaded operator is called, the mutex is locked, and the stream is flushed.
I've added some time/thread id debugging info to the output for verification purposes. So far, my testing shows that this method works. I have several threads pounding cout with multiple arguments, and everything is coming out in the right order.
From what I have read while researching this issue, lack of thread safety in cout seems to be a pretty common problem that people run into while venturing into threaded programming. What I am trying to figure out is if the technique I am using is a simple solution to the problem, or me thinking that I am clever but missing something important.
In my experience, the word clever when used to describe programming is just a code word for delayed pain. Am I on to something here, or just chasing lousy hacks around in circles?
Thanks!
What is not threadsafe here is not cout per se. It's calling two function calls in sequence. std::cout << a << b is roughly equivalent to calling operator<<(std::cout, a) followed by operator<<(std::cout, b). Calling two functions in sequence carries no guarantee that they will be executed in an atomic fashion.
As is, only the output of the time and thread id is protected by the mutex. It's perfectly possible to get another thread sneak in between the insertion of OUTHACK and val1, because the lock is no longer held after OUTHACK is inserted.
You can have operator<< for your OutputStreamHack return by value an object that unlocks in the destructor. Since temporaries live until the end of each full expression, the code would hold the lock "until the semicolon". However, because copies may be involved, this could be problematic without a move constructor (or a custom copy constructor in C++03, similar to auto_ptr's gasp).
Another option is to use the existing thread-safety of cout (guaranteed by the language in C++11, but many implementations were threadsafe before). Make an object that streams everything into a std::stringstream member and then write it all out at once when it is destroyed.
class FullExpressionAccumulator {
public:
explicit FullExpressionAccumulator(std::ostream& os) : os(os) {}
~FullExpressionAccumulator() {
os << ss.rdbuf() << std::flush; // write the whole shebang in one go
}
template <typename T>
FullExpressionAccumulator& operator<<(T const& t) {
ss << t; // accumulate into a non-shared stringstream, no threading issues
return *this;
}
private:
std::ostream& os;
std::stringstream ss;
// stringstream is not copyable, so copies are already forbidden
};
// using a temporary instead of returning one from a function avoids any issues with copies
FullExpressionAccumulator(std::cout) << val1 << val2 << val3;
i have a complex program with weird bug that some int value is down to zero unexpectedly.
so i want tracking this built-in type value, then i could debug easily.
to do that, i made following ValueWatcher template class so i could track almost changes of value except when ValueWatcher is dereferencing. (i made these dereferencing operators because the program needs int *, &)
template <typename T>
class ValueWatcher
{
public:
ValueWatcher(const T &val)
{
cout << "constructor with raw value " << val << endl;
_cur = _old = val;
}
ValueWatcher(const ValueWatcher& vw)
{
cout << "constructor with ValueWatcher " << vw._cur << endl;
_cur = vw._cur;
}
ValueWatcher& operator=(const ValueWatcher &rhs)
{
cout << "operator= with ValueWatcher " << rhs._cur << endl;
_cur = rhs._cur;
onChanged();
return *this;
}
ValueWatcher& operator=(const T &val)
{
cout << "operator= with " << val << endl;
_cur = val;
onChanged();
return *this;
}
int *operator&()
{
cout << "addressing operator" << endl;
// can't track anymore!!!!!!!!!!!!!!!!!!!!!!!!!
return &_cur;
}
operator int&()
{
cout << "operator int&" << endl;
// can't track anymore!!!!!!!!!!!!!!!!!!!!!!!!!
return _cur;
}
operator int&() const
{
cout << "const operator int&" << endl;
return _cur;
}
operator int() const
{
cout << "operator int" << endl;
return _cur;
}
private:
void onChanged()
{
// update old and do proper action
}
T _cur;
T _old;
};
the problem is, when client code wants int & or int * of ValueWatcher, - it can gives int & or int * anyway but - int * or & cannot hold ValueWatcher instance, so can't tracking anymore.
is there anyway to solve this? i think it can be solved by returning reference or pointer class instance instead of just returning & or * of built-int type. but i don't know how to do that.
in addition-
i can't run this program with debugger. the problem occurs only in REAL environment and very hard to reproduce.
If you can reproduce the behavior when running in a debugger, you should be able to set a value change or memory change breakpoint. This is probably easier than introducing a proxy implementation.
Its probably not the best solution, but what if your * or & return a pointer/reference to your value watcher? Otherwise I would forbid the use of * or &. (By not implementing it or making it private).
I don't think this is possible. Once you return an int* or int&, you've lost the ability to track anything. The only way (and the correct way, IMO) to do it that I can think of is to use a debugger and set a watch point with an appropriate condition. When the condition is met the debugger will interrupt and halt the program so you can inspect the memory, call stack, etc.
If you can spare a PAGE_SIZE bytes for your variable, then you can lock this part of memory using VirtualProtect (if you're on windows) - you can set read only access, for example. After that, anything that tries to access that variable will crash the program (so you'll be able to write memory dump and pinpoint routine that changes variable). I used this technique to pinpoint similar problem (multithreaded app, something was randomly overwriting memory blocks). If you can't debug machine immediately, try writing dumps using MiniDumpWriteDump . You will be able to debug memory dumps using WinDBG or Visual Studio.
If you're seriously desperate:
#define int ValueWatcher<int>
In a better scenario, you'd use
//typedef int intt;
typedef ValueWatcher<int> intt;
Then re-write all your code that wants an int and replace it. Replace int* with intt*. Replace int& with intt&.
You say you only see this problem when not debugging, so I'm guessing you have a bug which is obscure and can only be seen when building with optimizations. There are a couple possible explanations for this behavior:
You have a race condition somewhere
You didn't initialize a variable properly... so when building with optimizations you're values are initialized differently than when debugging.
You have a buffer overrun somewhere which is writing over one of your variables. Again, this could be something you only see when built with optimizations... When you build for debugging the compiler is going to leave extra space around variables on the stack... which acts as a cushion and can keep some bugs from revealing themselves.
Here is a relevant SO post which explains these issues in more detail:
Program only crashes as release build -- how to debug?