LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 11-01-2008, 04:56 PM   #1
everest40
Member
 
Registered: Jul 2008
Distribution: Ubuntu $LATESTVERSION
Posts: 160

Rep: Reputation: 64
Question private data member somehow gets changed (C++)


The program we are working on is fairly large, but the problem appears to be localized to one specific variable. We've tracked down the problem so far to a function getType() which returns -65536 (it shouldn't). getType()'s signature and body is below:

Code:
int myclass::getType()
{
  return returntype;
}
There is also a function setType():

Code:
void myclass::setType(int t)
{
  returntype = t;
}
These are the only functions which deal directly with returntype. returntype is also private and cannot be accessed outside this class. From looking through the code, it would appear to be impossible for setType() to be called with a value of anything less than -1. We've also tested this by adding a testing output in setType(). It does in fact never get set to -65536. However, our bug is caused when getType() mysteriously returns this.

This is obviously a strange issue, but perhaps someone with more experience can let us know if there is a particular problem that might be causing this or a particular way in which we should go about debugging this. A few other notes:

This exact program seems to work perfectly under Windows (compiled with MinGW) but fails under Linux (compiled with g++, tested on multiple computers. We've also checked for RAM problems.)

returntype is an int. We even tested that this is in fact a 32-bit signed integer. We don't have any idea why it gets set to -2^16... that seems like quite a coincidence.

We'd really appreciate any help or advice! Thanks!
 
Old 11-01-2008, 05:38 PM   #2
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
I will not mention too much that I think functions named get and set are pointless and that it would be better to maybe use constant reference types for the parameter and return type in addition the "get" function should really be constant.
Is the type set correctly in the constructor/copy constructor and assignment operators?

Last edited by dmail; 11-01-2008 at 05:39 PM.
 
Old 11-01-2008, 06:23 PM   #3
estabroo
Senior Member
 
Registered: Jun 2008
Distribution: debian, ubuntu, sidux
Posts: 1,094
Blog Entries: 2

Rep: Reputation: 111Reputation: 111
I'd bet your never initializing it and your requesting its value before its been set the first time. The windows compiler probably zeroes the memory and the linux compiler doesn't.
 
Old 11-01-2008, 06:37 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
I'd add a printf to setType and getType to see if the value is actually changed between a call to each. Also, private is a compile-time check, which by no means guarantees any effect at run-time.
ta0kira
 
Old 11-01-2008, 11:29 PM   #5
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 209

Rep: Reputation: 32
Are there any chances of overflow in your code???
 
Old 11-01-2008, 11:46 PM   #6
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
I was thinking of an overflow, also, but the closest overflow to -2^16 would be that of a signed short, which should actually be -2^15.
ta0kira
 
Old 11-01-2008, 11:49 PM   #7
TBennettcc
LQ Newbie
 
Registered: Sep 2004
Location: Fort Myers, FL, USA
Distribution: Fedora Core 4
Posts: 22

Rep: Reputation: 15
I second estabroo and say it's probably never getting initialized.

I've seen it happen before. In my experience, if you have a hugely negative number come from somewhere you're not expecting, first thing I would check would be to see where and how it was initialized to, and what value it was initialized with.

Don't forget: debuggers are your friends. If you have one available, learn how to use it. It will save you time.

Strange things happen to uninitialized variables!
 
Old 11-01-2008, 11:52 PM   #8
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Interdependent static initialization can also be a problem even if everything has been initialized...
ta0kira
 
Old 11-02-2008, 01:07 AM   #9
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
So what happens when you try:
Code:
myclass::myclass(...)
  : returntype(0)
{
  ...
}
 
Old 11-02-2008, 02:34 AM   #10
pinniped
Senior Member
 
Registered: May 2008
Location: planet earth
Distribution: Debian
Posts: 1,732

Rep: Reputation: 50
I'd attach a debugger and 'watch' the variable, interrupting on each change.

Other code problems can cause this sort of problem too - incorrect pointer (it doesn't matter that a variable is private; pointer=access), incorrect indexing within the class itself, reference to a *deallocated* object, operations on a deallocated object causing problems with an existing object - the list just goes on.
 
Old 11-02-2008, 07:23 AM   #11
nishamathew1980
Member
 
Registered: Oct 2008
Posts: 37

Rep: Reputation: 16
The best way to debug this is to add a break point for the getType() method and then run the application to identify at which point it is being invoked.
This will give you a much better idea on how the code flow is happening and why the value is getting messed up.


Hope this helps!


Linux Archive

Last edited by nishamathew1980; 11-09-2008 at 04:53 AM.
 
Old 11-02-2008, 06:36 PM   #12
everest40
Member
 
Registered: Jul 2008
Distribution: Ubuntu $LATESTVERSION
Posts: 160

Original Poster
Rep: Reputation: 64
Thanks for all your help. I appreciate all your advice.

The member variable "returntype" should be getting initialized every time the class is instantiated. There are three other classes which inherit from that one though (its an abstract class) and there is no constructor, but the constructors of each inheriting class contains a call to setType(). Depending on the situation in which the constructor gets called, it may put varying values into setType() but it should always get set. Would initializing the variable in this way be problematic?

estabroo's idea strikes me as the most likely overall, I have also seen that problem before. I don't think an overflow has anything to do with it, the smallest integer that should ever be set into returntype should be -1, and the largest should be a few thousand under most circumstances. Even if there were a case where a few million were set into it, the input this program is being run on would certainly not cause this.

We are currently using the gdb debugger but are not terribly experienced with using it. can someone point us in the right direction for figuring out how to have it tell us when returntype is changed?

There are as many as 20 instances of this class created however in this program, it might be confusing if it told us whenever any of them had a change in returntype. We would be able to tell which instance it was by a string variable "name".

Finally, I was interested in what dmail said. Were you suggesting that it should be:

Code:
const int& getType();
and
Code:
void setType(const int& t);
Perhaps I have misunderstood how references work under the hood, but wouldn't that take the same amount of work: copying a 32bit integer vs copying a 32bit pointer?

Thanks for all the help you've given already! It's much appreciated!

Last edited by everest40; 11-02-2008 at 09:10 PM. Reason: corrected a typo
 
Old 11-02-2008, 08:23 PM   #13
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by everest40 View Post
Would initializing the variable in this way be problematic?
Yes, normally that's a bad idea for a few reasons (sorry for the anthropomorphism of classes here.) The first is that it isn't really initialization; it's assignment after the base class has already been instantiated, and it makes tracking bugs like this a pain. For example, maybe you have a copy constructor in a derived class that doesn't set the value? Then you'd have a bad value stuck in the base class. Or maybe the constructor of a derived class calls another function of the base class before the set function is called, possibly causing a bad value to be used. Or maybe an intermediate class tries to use the value in its constructor erroneously thinking that it's being initialized beforehand by a class derived from it. Derived classes shouldn't need to "worry about" having to make up for shortcomings in base classes because it's standard for base classes to take care of themselves. For one, this duplicates your work if you revise the base class. The second reason is that most base classes should have no data members (there are some major exceptions, though, which I admit I heavily rely upon.) If it's generic enough to have several derived classes then you should think about making it abstract and forcing the derived classes to define the get and set methods. It's mostly about trivializing outside of the class changes within the class. If the only thing the base class does is provide get and set of that particular value, why does it need the value? You're probably better off making those pure virtual functions to be defined by the most-derived classes, which would store the member themselves. If the base class requires access then it can call the virtual functions.
ta0kira

PS
Quote:
Originally Posted by everest40 View Post
Perhaps I have misunderstood how references work under the hood, but wouldn't that take the same amount of work: copying a 32bit integer vs copying a 32bit pointer?
That's the way I see it, unless the reference/pointer is meant to stored instead of the value.

Last edited by ta0kira; 11-02-2008 at 09:40 PM.
 
Old 11-02-2008, 10:55 PM   #14
everest40
Member
 
Registered: Jul 2008
Distribution: Ubuntu $LATESTVERSION
Posts: 160

Original Poster
Rep: Reputation: 64
Thanks everyone! The bug turned out to be essentially that one of the derived classes did fail to call setType() after all and it was defaulting to 0 on windows and not on linux.

We are going to take your advice into consideration. Clearly this class could be more elegant and better organized.
 
Old 11-03-2008, 12:41 AM   #15
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
I'm glad you're taking the advice. I personally didn't take advice like this early on, so I've learned most of what I know the hard way (after hours/weeks of trying to make it work "my way" then failing miserably.) I'm very stubborn, though it can be very useful at times.
ta0kira
 
  


Reply

Tags
c++, g++, linux, member, mingw, variable, windows


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Date of transfered data has changed marciano Linux - Networking 3 11-11-2007 09:45 AM
Changed Partition Table Data Recovery Ext3 demmylls Linux - General 1 03-07-2007 05:44 AM
clear private data privileges firefox cornish Linux - Software 4 10-09-2006 07:03 PM
LXer: More Private Data Is Burgled From Government Than Hacked LXer Syndicated Linux News 0 06-21-2006 09:21 AM
device driver private data? kpachopoulos Programming 1 01-06-2006 04:13 PM


All times are GMT -5. The time now is 07:14 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration