Monday, May 16, 2011

How can you tell whether a loop ended prematurely?


Generally, loops are dependent on one or more variables. Your program can check those variables outside
the loop to ensure that the loop executed properly. For instance, consider the following example:
#define REQUESTED_BLOCKS 512
int x;
char* cp[REQUESTED_BLOCKS];
/* Attempt (in vain, I must add...) to
allocate 512 10KB blocks in memory. */
for (x=0; x< REQUESTED_BLOCKS; x++)
{
cp[x] = (char*) malloc(10000, 1);
if (cp[x] == (char*) NULL)
break;
}/* If x is less than REQUESTED_BLOCKS,
the loop has ended prematurely. */
if (x < REQUESTED_BLOCKS)
printf(“Bummer! My loop ended prematurely!\n”);
Notice that for the loop to execute successfully, it would have had to iterate through 512 times. Immediately
following the loop, this condition is tested to see whether the loop ended prematurely. If the variable x is
anything less than 512, some error has occurred.

What is the difference between goto and longjmp()
and setjmp()?

A goto statement implements a local jump of program execution, and the longjmp() and setjmp() functions
implement a nonlocal, or far, jump of program execution. Generally, a jump in execution of any kind should
be avoided because it is not considered good programming practice to use such statements as goto and
longjmp in your program.
A goto statement simply bypasses code in your program and jumps to a predefined position. To use the goto
statement, you give it a labeled position to jump to. This predefined position must be within the same
function. You cannot implement gotos between functions. Here is an example of a goto statement:
void bad_programmers_function(void)
{
int x;
printf(“Excuse me while I count to 5000...\n”);
x = 1;
while (1)
{
printf(“%d\n”, x);
if (x == 5000)
goto all_done;
else
x = x + 1;
}
all_done:
printf(“Whew! That wasn’t so bad, was it?\n”);
}
This example could have been written much better, avoiding the use of a goto statement. Here is an example
of an improved implementation:
void better_function(void)
{
int x;
printf(“Excuse me while I count to 5000...\n”);
for (x=1; x<=5000; x++)
printf(“%d\n”, x);
printf(“Whew! That wasn’t so bad, was it?\n”);
}
As previously mentioned, the longjmp() and setjmp() functions implement a nonlocal goto. When your
program calls setjmp(), the current state of your program is saved in a structure of type jmp_buf. Later, your
program can call the longjmp() function to restore the program’s state as it was when you called setjmp().
Unlike the goto statement, the longjmp() and setjmp() functions do not need to be implemented in the
same function. However, there is a major drawback to using these functions: your program, when restored
to its previously saved state, will lose its references to any dynamically allocated memory between the
longjmp() and the setjmp(). This means you will waste memory for every malloc() or calloc() you have
implemented between your longjmp() and setjmp(), and your program will be horribly inefficient. It is
highly recommended that you avoid using functions such as longjmp() and setjmp() because they, like the
goto statement, are quite often an indication of poor programming practice.
Here is an example of the longjmp() and setjmp() functions:
#include <stdio.h>
#include <setjmp.h>
jmp_buf saved_state;
void main(void);
void call_longjmp(void);
void main(void)
{
int ret_code;
printf(“The current state of the program is being saved...\n”);
ret_code = setjmp(saved_state);
if (ret_code == 1)
{
printf(“The longjmp function has been called.\n”);
printf(“The program’s previous state has been restored.\n”);
exit(0);
}printf(“I am about to call longjmp and\n”);
printf(“return to the previous program state...\n”);
call_longjmp();
}
void call_longjmp(void)
{
longjmp(saved_state, 1);
}