Link to home
Start Free TrialLog in
Avatar of klopter
klopter

asked on

What is the best way to catch unitialized variables?

Sometimes the compiler catches these for you,
but are there techniques or coding disciplines that
decrease the chance that these will slip through?

Ken
P.S.  I already commpile with -Wall
Avatar of chensu
chensu
Flag of Canada image

Use assert.
Avatar of nietod
nietod

Use constructors in EVERY class you write that initialize EVERY data member.  The penaltiy in size and speed due to unneccessary initializations will usually be very slight, the benefits in terms of programmer's hair loss....
avoid using ordinary C pointers and arrays directly.  Instead use C++ classes that encapsulate these, like smart pointers, and container classes like vector<>
Avatar of klopter

ASKER

nietod I think that your answer (using container
classes like vector<>) is probably the answer not
just to this question but also to my other question:

https://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=10260303 

In that question I post the following code.
If you can show me to convert this code to
use the vector<> class I will happily give you
the points for both questions.

Here is the code:

#include <fstream>

                 void subr() {
                   fstream *fout = new fstream[1];
                   fout[0].open("Afile", ios::out | ios::binary);
                   fout[0].close();
                 }




Thanks again,
  Ken
Initializing members isn't going to do much good, and seems like tautological advice to me.

Q: "How do I catch uninitalized variables?"
A: "Initialize all your variables."

Even if you initialize them, there's nothing that guarnatees the situation will be better. If you initialize a member pointer to zero, for instance, and just go ahead and dereference it without testing, you'll still crash.

If your compiler isn't catching everything, then you should consider using a lint tool that offers better diagnostics than your compiler.

If there are still some getting through, the bst tool at your disposal is aggressively doing peer reviews--hav your dev team get together and walk through the code in meetings. This helps education on the team substantially, and that in turn assures that component integration is smoother.

..B ekiM
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> Even if you initialize them, there's nothing that
>> guarnatees the situation will be better
Not completely true.  If they are initialized they will work consistently. If a pointer is initialized to NULL it will always cause a crash if dereferenced without being reset.  However, if variables are not initialized, they are unpredictable.  You may find that the code works well for a time being and then crashes.  The most common cause of this is code that uses data that global and is later switched to local.  For example, if you develop a class that contains a pointer and don't initialize the pointer.  If you init8ially work with objects of the class that are global, the pointer iwll always be initialized to NULL.  If your code tests for this and uses it as a semaphore, which is common, that the code might work perfectly.   However, when you create a local copy of the object, the pointer is not initialized.  Then when code test for the NULL pointer it finds it might not be NULL--crash.  There are plenty of other cases like this too.
>> you should consider using a lint tool that
>> offers better diagnostics than your compiler
VC has some nice features for this.  It can initialize variables and allocated memory to OCh (or other specified values) to help spot uninitialized "things"  It also has great features for tracking mistakes in allocating and freeing memory.
Avatar of klopter

ASKER

nietod - First let me say that I agree that an
initialized variabel is better than an unititialized
variable even if it is initialized ot he wrong value or used inappropriately - at least you get consistent results.

I played around with your suggestion on how to use the vector class but with no success.  fout.resize
generates 59 error messages from gcc -Wall.
Here is the file cut down to the minimum:

#include <fstream>
#include <vector>

using namespace std;
void subr() {
                 vector<fstream> fout;
             fout.resize(1);
}

The first few error messages are:

/util/include/g++/stl_algobase.h: In function `class fstream * __copy_d<const fs
tream *, fstream *, long int>(const class fstream *, const class fstream *, clas
s fstream *, long int *)':
/util/include/g++/stl_algobase.h:122: warning: conversion from `const fstream' t
o `fstream &' discards const
/util/include/g++/fstream.h:90: warning: in passing argument 1 of `fstream::oper
ator =(fstream &)'
/util/include/g++/streambuf.h: In method `class fstreambase & fstreambase::opera
tor =(class fstreambase &)':



Begin daunted by these error messages , I
thought that perhaps I could still make progress
by avoiding resize, so I tried:

#include <fstream>
#include <vector>

using namespace std;
void subr() {
  vector<fstream> fout[1];
  fout[0].open("Afile", ios::out | ios::binary);
}


Which yielded the following error messages:

what2.cc: In function `void subr()':
what2.cc:7: no matching function for call to `vector<fstream,__default_alloc_tem
plate<false,0> >::open (char[6], int)'
what2.cc:6: warning: variable `class vector<fstream,__default_alloc_template<fal
se,0> > * this' might be clobbered by `longjmp' or `vfork'


The first error message suggests that it can't
find open() anymore.  The second is the error
message that prompted this entire thread.

The good news is that I am learning about C++
with your help.

Ken
Avatar of klopter

ASKER

Adjusted points to 200
>Use constructors in EVERY class you write that initialize EVERY data member.

But there are still chances to forget to initialize it. Not to mention you will still need a lot of auto variables. And you may also initialize it to a wrong value.


By using assert extensively, you can make sure that the code is running under the control of your brain. Using assert not only helps debugging but also helps you think about the logics of the program.
Avatar of klopter

ASKER

Thanks nietod

I'll give you the oitns on this one  and hoipe
to continue the discussion on the other.

Ken
klopter> First let me say that I agree that an
 klopter> initialized variabel [sic] is better than an unititialized
 klopter> variable even if it is initialized ot he wrong
 klopter> value or used  inappropriately -

I think we all agree on that. All that nietod was saying (in that one post) is that one way to avoid uninitialized variables is to initialize them all. I'm pointing out that's tautological, and still not going to find the error until runtime.

 nieotd> VC has some nice features for this.  

Unfortunately, klopter isn't using VC++.

 chensu> But there are still chances to forget to initialize it.

Which is why you need to approach this problem with very robust tools or with code reviews. The more eyes, the less chance. The more experienced eyes, the better knowledge transfer.

..B ekiM
I aggree with chensu about the liberal use of asserts, (and I use them a lot!) but the problem is that programmer use them to test for mistakes that they think of an not the mistakes they don't think of.  And the mistakes you don't think of always outnumumber the ones that you do.   That asside, asserts are very useful in detecting all sorts of problems, including uninitialized varaibles.

Mike, I aggree with what you are saying, but klopter also askes

>> are there techniques or coding disciplines that
>> decrease the chance that these will slip through?

Thus I think my "answer" qualifies as a technique to prevent these sorts of problems.  And while I think code reviews are a great practice, I find that in OO code they are poor at finding uninitialized class members (Especially if your code standards don't demand explicit initialization of all members)..  This is because the initialization of class members often occurs far from their use.  Code reviewers are often looking in intently at the little details and often fail to pick-up larger problems in design, like this.

klopter

vector's look like arrays in most ways, but not all.,

>> vector<fstream> fout[1];

won't work--news to you?  But

  vector<fstream> fout(1);

should.  However, it sounds like you have other problems.
I'm not sure why you are getting those warnings.  However, they are warnings about removing "const" so I think you may be okay.  It suggests that the STL author was a a little careless in how the code was written (or it was old code that needs to be rewritten for the C++ standard) so it is reporting potential errors that probalby are not errors.

The secodn set of error messages are because of the [1] you had on fout, remove that and you should only have warnings.
nietod> I find that in OO code they are poor at finding
 nietod> uninitialized class members

Then, you need to have more disciplined code reviews. Class members are all written down, and their initialziation patters are easily recognizable. You need to use those reviews to instil more disciplined techniques on your team.

C++ offers the ability to freely move variable initializations closer to where they're used. You should also instill that discipline.

 nietod> the liberal use of asserts

That doesn't find the problem at compile time, which is what klopter has asked about.

..B ekiM
>> That doesn't find the problem at compile time,
And can give a false sense of security as some areas of code might not be tested until the user does so on a release version.

>> C++ offers the ability to freely move variable
>> initializations closer to where they're used. You
>> should also instill that discipline.
In a class?  The data members have to be initialized in a constructor.  And the data members may be used outside of the constructor.  A clear set of invariants and pre- and post-conditions should prevent this from being a problem, but in practice people are lazy.  

>> You need to use those reviews to instil
>> more disciplined techniques on your team.
amen.