C++ Tracking primitive type value change

L

ljh131

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.
 
Ö

Öö Tiib

i have a complex program with weird bug that some int value is down to
zero unexpectedly.

It usually happens because some code is accessing some other array
outside of its bounds.
so i want tracking this built-in type value, then i could debug
easily.

Yes for example number of debuggers have conditional breakpoints that
break when data in memory location changes.
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 *, &)

(snip)

You must somehow use it instead of int. That seems impossible.
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.

If you had used some "typedef int Lattitude;" for and then used
"Lattitude" everywhere as type of that particular variable instead of
"int" then it would be easy to replace. Using preprocessor like
"#define int ValueWatcher" is forbidden by standard.

Can not you just step in debugger to find out exact moment when the
value is changed?
 
L

ljh131

thanks to your reply, but i can't use debugger or something because i
can't reproduce this bug.
the problem occurs only in real condition (just once or twice by many
users per day)

so i want these techniques to solve this problem easily.
 
F

Francesco S. Carta

ljh131 said:
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.

As a side note, you shouldn't use names starting with an underscore -
that range of names is reserved for the implementation. As Öö Tiib
suggested, stepping through the program with a debugger is advisable.
Breakpoints, conditional breakpoints and watchers will help you.

If you can touch the client code, you could do some debugging by hand
- that is, nail down the moment that the bug appears by printing out
the misbehaving variable at the entrance and at the exit of the
functions - also consider using some asserts in the critical points -
i.e. before calling a function that expects that variable not to be 0.

Hope that helps.
 
F

Francesco S. Carta

ljh131 said:
thanks to your reply, but i can't use debugger or something because i
can't reproduce this bug.
the problem occurs only in real condition (just once or twice by many
users per day)

Well that is not nice, at all...

Francesco S. Carta said:
As a side note, you shouldn't use names starting with an underscore -
that range of names is reserved for the implementation.

Uh, maybe here I recall wrong, one underscore followed by a lowercase
letter should be fine.
 
M

Marcel Müller

Hi,
thanks to your reply, but i can't use debugger or something because i
can't reproduce this bug.
the problem occurs only in real condition (just once or twice by many
users per day)

is your integer unmodified once the application is initialized?
If so you could run the application in the debugger the whole day with
only a data breakpoint to your integer set. If your hardware supports
that, there will be no performance impact.
so i want these techniques to solve this problem easily.

You will only capture accidental program flow this way. If you have
undefined behavior, e.g. as result of a race condition, your solution
will not trigger. Also the memory layout of your class is different from
int. This may modify the symptom.

But you can improve your class and store an shadow copy with the 1's
complement of the value. Any read access can prove the shadow for
consistency. It is very unlikely the a data bomb will keep the
consistency of the 1's complement. However, unlike a data-point this
will only trigger when the variable is read. So you might need to add
additional (unneeded) read access to your integer at certain places in
your code.


Marcel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top