Monday, April 7, 2014

The code does what it is instructed to do, not what you intend it to do”.

Every programmer would have experienced that feeling of relief which usually occurs about 2:00 in the morning as you finally find and fix that one last bug that has been bothering you for the past few days.

A bug usually occurs because of the unhandled, not thought of scenarios, incorrect design, incorrect understanding of design, bad coding practices, race conditions and few more. It is not always easy to reproduce bugs as they are triggered by inputs to the program which may be difficult for the programmer to recreate. One cause of the Therac-25 radiation machine deaths was a bug, specifically a race condition that occurred only when the machine operator very rapidly entered a treatment plan. The bug wasn’t tracked in testing or when the manufacturer attempted to duplicate it.

So we have to minimize the bugs to an extent that the leftover bugs can never ever occur.

Journey towards a bug free programming

Learn the dirty details:
The very minor details of how the hidden parts of your language, application and technology work are very important. By scrutinized understanding of those, you can avoid writing complicated code or could avoid the parts that have their own bugs.

Visit all the scenarios that a control can:
The unhandled scenarios would strike in later after the deployment. Handle all the scenarios that your code can go in. This is the effective step in isolating the bugs.

Unbreakable Design:
Design your applications carefully by writing down the relevant events and the way your code will respond to each one. Give each event procedure and each general procedure a specific, well-defined purpose.

Fix the underlying cause, not the symptom:
When you fix a bug, make sure you are really addressing the underlying cause or problem of the bug and not just the symptom of the bug.

Counter Memory Leak:
Memory leak is a situation, where the memory is allocated to the program which is not freed subsequently. This kind of situation could lead to ever increasing usage of memory and at some point of time, the program may have to come to an exceptional halt because of the lack of free memory. Avoid memory leaks by releasing the memory accordingly.

Sending letters to a dead person:            
The variables declared in a function represent data which is limited to that function and will be stored in the stack associated with that function. Avoid returning these references as they would get destroyed when the control leaves that function.

No Vacuum Dereferencing:
Incorrect initialization and missing the initialization of objects in different paths leads to the NULL reference error. Whenever an object is being dereferenced, make sure that it has been initialized in all possible paths to the point of dereferencing.

Wrong assumptions on operator precedence:
This is a common error which is not directly visible and the results are not as expected. This is more dependent on the programmer’s logic in coding. Learn the precedence rules of the programming language. Do not write big and complicated expression. The best and safe programming is to use parenthesis to avoid the confusions.

Non-Zero based indexing:
The programmer by using Non-Zero based indexing unknowingly modifies random memory which will cause memory corruption.

Buggy Redundant Work:
This a common form of bug where the programmer tries to free the already freed resource or releasing (winding up references) which are already released. This may be more erroneous, if we have some allocation statements between the two memory released statements. There is a chance that the first freed locations are now allocated to the new variable. And the subsequent free will deallocate the new variable.

Correct usage of Aliases:
When there is unexpected aliasing between parameters, return values, and global variables, errors may be inevitable. Aliasing problems sometimes lead to deallocation errors. Static analysis of all feasible paths in the program can detect possible aliases.

Guarding Synchronization Errors:
In multi-threaded programming when there are multiple threads which are accessing resources, there is fair chance of causing synchronizing problems. Deadlock detection and avoidance are the possible strategies to be followed and extreme handling of race conditions has to be followed.

No to Buffer overflow:
Buffer Overflow is an anomalous situation where the data is written beyond what it is assigned. This has to be avoided by conditional writing with available buffer.

Keep an eye on the Exceptions:
Exceptions handling is the heart of handling bugs. There may be innumerable ways in which one’s code may fail. So, it is the programmer’s job is to see all possible data paths in the program and write the necessary exception handlers. When writing error handlers in the code, analyze the state of the system during exceptional handling and see that the system will be in allowed consistent state after the exception and handling.

Logical Breaks in Macro Programming:
Use typedef to define types not macros when defining pointers to objects. Also use constants, inline functions instead of macros which avoid logical errors. If you desperately want to use macros the use, then use parenthesis extensively to avoid logical bugs.

Maintainable Code
Strive to write code that is understandable by other programmers. Good code runs. Great code runs and is also easily maintainable.

Validate Data:
Preconditions, post conditions ensure that provided data and the state of the program as a whole is hygienic. Check arguments to a function or method for validity before and executing the body of the function. Do not trust the libraries you did not write and when you use them, check the validity of the data.

See the below example for how a bug can be introduced.
int div(int *dividor)
{
int result = 5;
result=result/*divisor;   /* Divide and store it in result */;
return result;
}


We have to give spaces around the operators to avoid bugs. In the above example /*divisor is treated as a comment in priority and hence the result is a plain assignment.