Tuesday, 10 August 2010

Segmentation faults with pointers in C...

Segmentation fault occurs when an attempt is made to access unallocated memory.
Segmentation faults with pointers might prove to be a task to deal with .This is mainly because of the fact that the actual area of the fault has to be identified and then the fault cleared. This might sometimes leave you in a pondering state. If the reasons that cause the segmentation faults are known , then it might help us to get rid of it quite quickly...
The major reasons for the segmentation fault to occur while using pointers might be the following..
Dereferencing NULL
and dereferencing an uninitialized pointer.
Both these cases would result in segmentation fault.

Whenever a segmentation fault occurs-the best way to deal with it is to find out the point of occurrence at first and then find out exactly why it happened..
The best way to spot a segmentation fault is to install gdb on your system.
This would enable you to find out the point of occurrence of the fault and the fault can be cleared.
The best practice while using pointers is always to initialize the pointer to NULL at first. Therefore when using the gdb you can see the null value( as 0x0 in systems)
/* consider a section of the debugging process*/

51 *dayofmonth=yearday;
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x0804862f in year_day (year=12, yearday=15, dayofmonth=0x0, month=0x0) at pmonthday.c:51
51 *dayofmonth=yearday;

*/


Here my pointers are 'dayofmonth' and 'month'..Hence from the debugging process its clear that the pointers have been set to NULL which indicates that we have not initialized the pointer to a legal memory address.
Again there are other methods identify the problem. Print all the values of pointers used in the program and see if any value differs from the others by a far long distance. If yes,this address space might be illegal. But theres no guarantee that this would be a solution.
Of course it may happen that sometimes you might get lucky with uninitialized pointers and there might be no segmentation fault, but its better not to make a habit of that because you might a segfault anytime. Hence its always better to initialize the pointer to NULL at first and then to a legal address.
A segmentation fault could be cleared by just setting the pointer to some legal address.
For an eg..
'p' is the uninitialized pointer that has caused the fault, just set it to the base address of an array as
char array[1000];
char *p=array;

Static variables and declarations...

The static declaration can be applied to both external and internal variables. The static declaration if applied to external variables limits the scope of that particular variable to the rest of the source file being compiled. Static declaration if applied to the internal variables ensures that the variables returns its previous value after the control has been transferred out and in of the particular function...i.e it provides permanent storage for the variable rather than temporary storage which is the case with normal internal variables.

Lets see how static works with internal variables...
Consider the program code...

char yes(void)
{
static int lastc=0;
lastc=lastc+1;
return lastc;
}
The variable lastc has been declared static:
Hence the value of lastc remains intact even after the function 'yes()' has terminted...lastc will get back its older value when the next call to the function 'yes()'arrives.
Therefore if the return values where to be printed...it would be as following:
1
2
3
...
...

This obviously wouldn't have been the case if the static declaration was not provided.
Now consider the case:

char yes(void)
{
static int lastc;
lastc=0;
lastc=lastc+1;
return lastc;
}

Here the initial value of the variable has been assigned after the static declaration is performed.
This would result in a normal execution. Obviously the variable would be static and has permanent storage but its that just the assignment operation after the static declaration takes its effect. Therefore its highly important to initialize the value of the variable declared 'static' along with declaration.

Sunday, 8 August 2010

Debugging with the GDB

GNU debugger(GDB) allows you to view the step by step execution of the program code. This proves of great help in executing complex programs(specially the ones involving recursion) to see the exact flow of control. How to debug using the gdb and a few options used are worth notable:
To debug a program with gdb , steps followed are
'cc -g file.c'
gdb a.out. ....'a.out is your executable...'
You will see messages about the gdb version displayed on the terminal....
Now set the break point by
'break main'
Use the 'run' command to start running the program.
The 3 commonly used options are 's' ,'n' ,'q' with the gdb are…
's' moves to the next line of code-it enters functions as well.
'n' moves to the next line of code as well but does not enter functions.
'q' is used to quit from the process.

A debugging process would be like this...

sunil:~/new# cc -g quicksort.c
sunil:~/new# gdb a.out
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...

(gdb) break main
Breakpoint 1 at 0x80483e5: file quicksort.c, line 7.
(gdb) run
Starting program: /root/new/a.out
Breakpoint 1, main () at quicksort.c:7
7 int left=0,right=4,i;

(gdb) s
8 int array[]={4,8,1,9,3};
.../*
...continue the process...
.../*

(gdb) q
Quits from the debugger

Recursion in C..

Recursion may be used in C programs, where one function may be called within itself. The method of recursion will be simpler to understand with a small program code. The code is as follows.

#include
void printd(int n)
{
if (n < 0) {
putchar('-');
n = -n;
}
if (n / 10)
printd(n / 10);
putchar(n % 10 + '0');
}

The program is used to convert an integer decimal into its character digits.i.e 123 will be converted into 1
2
3
....the digits of the integer.
Lets see how the code works.
Consider the initial value of n as 123.
printd(123) //level 1
123/10 is true:Hence
printd(123/10);

printd(12) //level 2
12/10 is true:Hence
printd(12/10);

printd(1) //level 3
1/10 is not true;
hence putchar(1%10+'0'); //1 is printed
}

Now the call to the completed function printd(1) came from the function printd(12/10)(level 2) and the control returns to the end of the function printd(12/10) (n being 12)
The next statement is
hence putchar(12%10+'0'); // 2 is printed

Again the call to the completed function .i.e (printd(12)) is not from the main, but its from the function printd(123/10)(level 3) and hence the control is returned to the end of the function(n being 123).
The next statement is
hence putchar(123%10+'0'); // 3 is printed
Now the call to completed function(printd(123)) came from the main() and the control is returned there and the program proceeds.

Hope this gives a basic idea of the working of recursive functions. The function used in quick sort algorithm for sorting would be a good way to understand the working of recursion in a better way.

Saturday, 7 August 2010

A bit about bitwise operators....

Before we get a view of the bitwise operators , its important to have an idea of sizes of different types that are used in C.
Since most of the values that are entered by us can be accommodated by the ‘type float’ we consider the int , short and char types.
The data type char occupies a space of minimum of 8 bits(1 byte).The maximum value that can be placed in an unsigned char without the problem of truncation is 255. In case of unsigned char, this value moves to 127.The minimum value in signed char is -128.
The type int stores a maximum value of 65,635 for unsigned type and a maximum of 32767 for the signed type(these are the minimum values offered by any system, the actual limits may change on different systems). The minimum for the signed type would be -32768.The minimum number of bits required for storage would be 16. These values are the same for the type ‘short’.
These were some of the basics that were needed to get an idea about the bitwise operators. Obviously playing with the bits is a bit more difficult task than the higher level.
The bitwise operators are
&-bitwise AND
|-bitwise OR
<>-right shift
^-exclusive or
~-bitwise complement.

<<-left shift operators would be the best way to get an idea about the bitwise operators.
Consider doing the following
255<<2….the result would be 1020….255<<3 would give you 2040…255<<4….would give you 4080….and so….
Lets see how this works….doing 255<<2 is equivalent to doing 255*2^2(here the ^ symbol stands for the ‘raise to’ operator….Similarly 255<<3 is equivalent to doing 255*2^3….
A smaller number would help in understanding this.
Left shift operator shifts each bit of the character 2 places to the left. In the case 1<<2…would give 4 as the answer…
1(00000001)<<2=00000100(4)….This is how you obtain 4 as the answer.
Now the importance of the knowing the bit size of different types comes in here…
Suppose that the character 255 has been stored using variable of the type ‘char’…Now it is obvious that after shifting it to left, the result cannot be held by the type ‘char’ because the maximum value that can be stored in ‘type char’ is 255..Therefore it will have to be stored in the type whose size is greater then that of ‘char’.
.unsigned char s=255;
.s=s<<2; wouldn't be correct.
We use the type 'int' to store the result...
.unsigned char s=255;
.int i=s<<2; is the right way to do it..
Similarly its also important to consider the limits of the signed and unsigned values when using the shift operators.
The attempt to shift more bits than is allotted would produce in a message as ‘>=width of the type’.
The other bitwise operators work on the bits as follows….
>>p --- shifts the bits p positions to the right…equivalent to dividing with 2^p.
'&' ---result is 1 when any of the bits are 1…
^,|,~ all work in their own way….

The 'lm' option.

It may sometimes happen that when you use commands like sin,cos,pow etc....you get a warning message like 'undefined reference' .This may happen even when you have included the header file .This happens because your program has not been linked with the system library properly...
A solution to the situation would be to use the option 'lm' when you compile the file.This would fix the problem and the call would be referred to the function definitions in the system's library.
The syntax would be as follows....
'gcc -lm filename.c'

Tuesday, 3 August 2010

Files in the Unix file system and their permissions...

A file is a sequence of characters. A few commands and knowledge that may help in dealing with files and directories in UNIX are the following.
The 'ls' commands and its variations :
The 'du' command and its variations
The command used to change the permissions – 'chmod'.
A look into these commands
ls command gives a listing of all the files that are present in the current directory.
The 'ls -l' is used to provide a detailed listing of the files that are present.
For eg. If you type the command 'ls -l' the results be will produced as
-rw-r--r-- 1 root root 856 2010-08-03 20:15 delete.c

-rw-r--r-- 1 root root 868 2010-08-03 08:19 line.c

where line.c and delete.c are the two files present in the directory.
The other variations of the command include ls-u,ls-t etc
The 'du' (disk usage)provides information about the usage of the disk.
The command 'du -a' is used to provide disk informations about even the files of subdirectories.
The 'du-a|grep line.c'
provides the details about the file 'line.c'.
'chmod' is the command that is used to change permissions. The permissions can be changed by the superuser.
Consider the following permissions:
-rwxrwxrwx - indicates that the owner,the group and the other users of the system can all read(r),write(w)and execute(x) the file of which the permission has be shown.
Inorder to change the permission , the 'chmod' command is used.
For eg. 'chmod 666 file'
indicates that the file can be read and written by all the three categories of users mentioned above.
The octal values have their meanings as
4-indicates that the file can be read
2-file can be written
1-file can be executed
therefore 'chmod 444 file' would set the permissions of the file to read only for all the categories of users.
6 6 6 indicates(4+2 4+2 4+2) for the three users.)
Now do 'ls -l' and you will see the permissions as
-r--r--r--.
'+' is used to turn a permission on and '-' to turn it off.
The command 'chmod +w file' enables write permissions for the file
and 'chmod -x file' turns off the execute permissions for the file.
The permissions of the file can be viewed using the 'ls -l' command stated before. The permissions of the directory cab also be set and viewed using the 'ls -ld' command.
The 'ln','cp','mv' commands are used in UNIX for slightly different uses.
The 'ln command creates a link to the file. Therefore the same file can be accessed using the two file names. The syntax is as follows:
'ln filename filename1'
You would obtain another link to the file named 'filename' by the name of 'filename1':
The change made to original file would reflect in the other as well. You could see that with help of the 'ls -i' (command that indicates the 'i-number' of the file)that the two files that are linked are having the same i-number.
'cp' command is used to make the copy and the 'mv' command is used to move or rename files.
The command 'mv filename1 filenname2...... destination directory' is used to move several files together to the destination directory.