7

As per the title, I am planning to move some legacy code developed a decade+ ago for AIX. The problem is the code base is huge. The developers didn't initialize their pointers in the original code. Now while migrating the code to the latest servers, I see some problems with it.

I know that the best solution is to run through all the code and initialize all the variables whereever required. However, I am just keen to know if there are any other solutions available to this problem. I tried google but couldn't find an appropriate answer.

Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125
kris123456
  • 501
  • 1
  • 5
  • 15
  • 2
    Did your compiler on AIX initialize them for you? Does the code depend on value(s) in uninitialized memory? If the answer to both of those is "No", then you might just try compiling the code on the new server and seeing what happens. Your code may be horribly unsafe in theory, but in practice it might Just Work. – Michael Kristofik Jan 22 '13 at 16:03
  • 2
    What does "i see some problems with the code." mean? Is it that you are actually seeing failures, or simply that you are spotting that "this pointer isn't initialized, but maybe that's not a problem"? Initializing pointers that are later on set to a different value unconditionally serves no purpose in and of itself [it may make it clearer that it DEFINITELY is set to something]. – Mats Petersson Jan 22 '13 at 16:07
  • 1
    The best solution is to initialize all the pointers. There is no safer method. – andre Jan 22 '13 at 16:12
  • 1
    related: http://stackoverflow.com/questions/2099692/easy-way-find-uninitialized-member-variables – akira Jan 22 '13 at 16:19
  • 4
    The first step could be just to compile your code with a recent version of `g++` with `-Wuninitialized -Winit-self -O2` and have a look at the locations pointed out by the resulting warnings. This should at least show the worst offenders. – Matteo Italia Jan 22 '13 at 16:31
  • If the code currently works correctly, don't mess with it until you have a solid baseline on the new platform. Recompile it as is and run the test suite. – Pete Becker Jan 22 '13 at 17:01
  • If the code base is truly huge, rather than just using the eyeball-test, I would run it through `valgrind` to verify that indeed, those variables have been read before assigned (uninitialised read). I would fix the ones that valgrind flags first. – kfmfe04 Jan 23 '13 at 01:28
  • If the code base is really big, customizing the GCC compiler (at least for exploration, metrics, navigation, refactoring purposes) could make sense (but does take time). Maybe http://gcc-melt.org/ could be relevant. – Basile Starynkevitch Jan 23 '13 at 06:48

2 Answers2

2

The most preventive long-term approach is to initialize all pointers at the location they're declared, changing the code to use appropriate smart pointers to manage the lifetime. If you have any sort of unit tests this refactoring can be relatively painless.

In a shorter term and if you're porting to Linux you could use valgrind and get a good shot at tracking down the one or two real issues that are biting you, giving you time to refactor at a more leisurely pace.

Mark B
  • 95,107
  • 10
  • 109
  • 188
2

Just initializing all the variables may not be a good idea.

Reliable behavior generally depends on variables having values known to be correct ("guaranteed by construction" to be correct). The problem with uninitialized variables isn't simply that they have unknown values. Obviously being unknown is a problem, but again the desired sate is having known and correct values. Initializing a variable to a known value that is not correct does not yield reliable behavior.

Not infrequently it happens that there is no 'default' value that is correct to use as a fallback if more complicated initialization fails. A program may choose not to initialize a variable with a value if that value must be over-written before the variable can be used.

Initializing a variable to a default value may have a few problems in such cases. Often 'default' values are inoffensive in that if they are used the consequences aren't immediately obvious. That's not generally desirable because as the developer you want to notice when things go wrong. You can avoid this problem by picking default values that will have obvious consequences, but that doesn't solve a second issue; Static analyzers can often detect and report when an uninitialized variable is used. If there's a problem with some complicated initialization logic such that no value is set, you want that to be detectable. Setting a default value prevents static analysis from detecting such cases. So there are cases where you do not want to initialize variables.


With pointers the default value is typically nullptr, which to a certain extent avoids the first issue discussed above because dereferencing a null pointer typically produces an immediate crash (good for debugging). However code might also detect a null pointer and report an error (good for debugging) or might fall back to some other method (bad for debugging). You may be better off using static analysis to detect usages of uninitialized pointers rather than initializing them. Though static analysis may detect dereferencing of null pointers it won't detect when null pointers cause error reporting or fallback routines to be used.


In response to your comment:

The major problems that i see are

  • Pointers to local variables are returned from functions.
  • Almost all the pointer variables are not initialized. I am sure that AIX does provide this comfort for the customer in the earlier platform however i really doubt that the code would run flawlessly in Linux when it is being put to real test (Production).
  • I cannot deliver partial solutions which may work. i prefer to give the best to my customer who pays me for my work. So Wont prefer to use workarounds.
  • Quality cannot be compromised.
  • fix them (and pay special attention to correctly cleaning up)
  • As I argue above simply lacking an initializer is not in and of itself a defect. There is only a defect if the uninitialized value is actually used in an illegal manner. I'm not sure what you mean about AIX providing comfort.
  • As I argue above the 'partial solution' and 'workaround' would be to blindly initialize everything.
  • Again, blindly initializing everything can result not only in useless work, but it can actually compromise quality by taking away some tools for detecting bugs.
bames53
  • 86,085
  • 15
  • 179
  • 244
  • The major problems that i see are -Pointers to local variables are returned from functions. -Almost all the pointer variables are not initialized. I am sure that AIX does provide this comfort for the customer in the earlier platform however i really doubt that the code would run flawlessly in Linux when it is being put to real test (Production). -I cannot deliver partial solutions which may work. i prefer to give the best to my customer who pays me for my work. So Wont prefer to use workarounds. -Quality cannot be compromised. – kris123456 Jan 23 '13 at 17:34