-
  home |  testing services |  automation |  development |  training |  downloads |  clients |  about us |  contact us 
#
LogiGear Download FREE articles, presentations, white papers and more!

home >> resources >> Common Software Errors >> Initial and Later States

>>
>> Home
>> Resource Center
>>
Latest articles
Classic articles
Articles by others
Resource directory
>> White papers
>> Newsletter archives
>> RSS feed
>> Books
>> Contact us

Ask us now on live chat...


For more information:
Contact Us

Printer friendly:
PDF version

LogiGear Resource Center

AddThis Social Bookmark Button

Testing Computer Software Second Edition

Common Software Errors - Initial and Later States


This is the appendix from the best-selling book
Testing Computer Software, 2nd ed.

Copyright © 1988 by Cem Kaner
Copyright © 1993 by Cem Kaner, Jack Falk, Hung Quoc Nguyen

This is part 6 of 13.

[ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ]
[ 10 ] [ 11 ] [ 12 ] [ 13 ]

Initial and Later States

Before you can use a function, the program may have to initialize it. Typical initialization steps include identifying the function's variables, defining their types, allocating memory for them, and setting them to default values (such as 0). The program may have to read a disk file that contains defaults and other configuration information. What happens when the file is not there? Initialization steps might be done when the program is loaded (data defaults can be loaded into memory along with the program), when it is started, when the function is first called, or each time the function is called.

Initialization needs and strategy vary widely across languages. For example:

  • In many languages, a function's local variables keep their values from one call to the next. If a variable is supposed to keep the same value, the function can set the variable's value once and leave it alone thereafter. The function usually has to reset other variables to their starting values.
  • In other languages, local variables are erased from memory on exit from the function. Whenever the program calls a function, it must redefine its variables, allocate memory for them, and assign starting values.
  • Some languages allow the programmer to specify whether a variable should stay in memory or be erased after each function call.
  • Some compilers provide initialization support. The programmer can specify a starting value for a variable; the compiler will make sure that this loads into memory with the program. If the programmer doesn't assign an initial value, the compiler sets it to 0. Other compilers, even for the same language, do not provide this support. The function must set each variable's value the first time it's called. To avoid resetting each variable every time it's called, the function must know whether it's been called before.

Initialization failures usually show up the first time the function is called or the second time, if it doesn't reinitialize variables correctly. Reinitialization failures may be path-dependent. If you reach a function in a "normal" way, it works fine. However, if you take an "abnormal" route, the program might branch into the function at some point after the initialization code. Programmers often treat backing up to modify data or redo calculations as abnormal.

FAILURE TO SET A DATA ITEM TO 0

Since so many compilers, in so many languages, set data to 0 unless you tell them otherwise, many programmers don't bother specifying the starting value of a variable unless it is nonzero. Their coding style fails as soon as they use a compiler that doesn't automatically zero data.

FAILURE TO INITIALIZE A LOOP-CONTROL VARIABLE

A loop-control variable determines how many times the program will run through a loop. For example, a function prints the first 10 lines of a text file. The program stores the number of the line reaches 11, printing stops. Next time, the function must reset LINE to 1 or it will never start printing because LINE's value is 11 already.

FAILURE TO INITIALIZE (OR REINITIALIZE) A POINTER

A pointer variable stores an address, such as the location in memory where a given string starts. The value of the pointer can change-for example, it might point to the first character in a string, then be changed to point to the second, the third, and so on. If the programmer forgets to reset a pointer after changing it, it will point to the wrong part of the string or to the wrong string. If subsequent function calls keep changing the pointer without reinitializing it, the pointer may eventually point to code rather than data.

You should suspect pointer errors if you see string fragments or incorrect array elements displayed.

FAILURE TO CLEAR A STRING

A string variable stores a set of characters. Whereas the value of a numeric variable might be 5, a string might have the value Hello, my name is John. Strings can vary in length. You can change the string from Hello, my name is John to the shorter string, Goodbye. Some routines assume that a string is empty (filled with zeroes) before they use it. A routine that writes Goodbye into the first 7 bytes of a string without terminating it with zeroes might yield Goodbye my name is John rather than Goodbye.

FAILURE TO INITIALIZE (OR REINITIALIZE) REGISTERS

Registers are special memory areas usually found on the central processing unit itself. You can manipulate data stored in registers more quickly than those stored in normal memory. Because of this speed advantage, programs constantly use registers for temporary storage. They copy a few variables' values to registers, work with them, and copy the new values in the registers back. It's easy to forget to load the latest data into one of these registers.

FAILURE TO CLEAR A FLAG

Flags are variables that indicate special conditions. A flag can be set (true, on, up, usually 1) or clear (false, off, down, usually 0 or -1). The flag's value is normally clear. It is set as a signal that a routine has failed, that its variables have been initialized, that the result of a calculation was an overflow or an underflow, that you've just pressed a key, etc. Less desirably, but also common, a flag might tell a routine that it was called from one place in the program rather than another, or that it should perform one type of calculation rather than another.

The flag must be kept current. For example, a routine should clear its error flag each time it's called, returning with a set flag only when it fails. A routine should clear its data-initialized flag whenever any of its variables change from default values that should be changed back the next time the routine is used. Some programs can set or clear the same flag in a dozen different places. It's hard to tell whether the flag's value is current or not.

DATA WERE SUPPOSED TO BE INITIALIZED ELSEWHERE

A function may not initialize all of its data. For example, variables shared by different functions might be initialized together. Suppose that some functions are listed in the same menu, and their shared variables are initialized whenever that menu is displayed. This works as long as there's no other path to any of these functions, but can you reach one by a back door? Is any function an option on another menu? Might the program call it as part of another function's error recovery?

FAILURE TO REINITIALIZE

Programmers may forget to make sure that a function's variables have the right values the second time around. Simple forgetfulness is especially common when dealing with languages that automatically initialize variables to 0. The programmer didn't have to set it to 0 for the first pass through the function. Why should she think about setting it back to 0 later?

The programmer might also fail to reinitialize a function's data when it's reached "by the back door," especially when you try to back up to change data. Imagine entering data on a form, displayed onscreen. The program initializes all relevant variables when it paints the form. You enter the wrong number, notice it after entering a few other values, move the cursor back, and fix it. Any calculations based on this number now have to be redone. Will the variables in those calculation sections be reinitialized? Moving backward in the program is risky as far as variable reinitialization is concerned. The risk is much higher if the programmer uses GOTOs to move back to lines in the middle of a block of code, rather than at the start of it.

ASSUMPTION THAT DATA WERE NOT REINITIALIZED

Some programs initialize the same variables repeatedly, before they could have changed. This is harmless, except for the waste of computer time.

CONFUSION BETWEEN STATIC AND DYNAMIC STORAGE

A local variable is called dynamic or automatic if it is erased from memory when the function that owns it exits. Each time the program calls the function, it has to redefine the variable, allocate memory for it, and assign starting values. A static variable stays in memory and keeps its value across function calls. In some languages, all local variables are dynamic, in others all locals are static, and in some, the programmer gets to choose which variables are static and which dynamic. When both types of variables exist, confusion is easy. The programmer might forget to reinitialize a static variable because she thinks it's dynamic, and so doesn't need initialization. Similarly, she might forget to update the value of an automatic variable because she forgets that it doesn't keep its value across function calls.

DATA MODIFICATION BY SIDE-EFFECT

After initialization, a routine might use a variable without changing it. The programmer might consider reinitialization unnecessary, since the variable doesn't change, but even if she intends the variable to be local to that routine, the language she's writing in might not recognize the concept of local variables. Any other part of the program can change this variable; after much maintenance, any other part of the program might.

INCORRECT INITIALIZATION

The programmer might assign the wrong value to a variable, or declare it integer instead of floating point, static instead of dynamic, global instead of local. Most of these errors are caught by the compiler, long before you see the program.

RELIANCE ON TOOLS THE CUSTOMER MAY NOT HAVE OR UNDERSTAND

This is rare but it happens-it's surprisingly easy to miss. The programmer expects you to use some other program to modify this one or to set up some aspects of the program's environment. You must do this the first time you use the program, to get its memory limits or whatever into the right initial state. Thereafter, as the tester, you may forget that you ever did it.


-
newsletter | RSS | site map |

1 (800) 322-0333   © 2009 LogiGear Corporation. All rights reserved.   Legal Notice.   Privacy Policy.