ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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!
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?
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.
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
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.
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.
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.
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
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
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.
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.
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
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.