Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Saturday, January 26, 2008

Where are your tools ?

A new year brings with itself a new hope, a revived enthusiasm to set up things in your life in order. That's exactly the purpose of this post. I intend to help some students who are willing to strengthen their programming skills this year.

I have observed that a number of students in colleges who like to program in C, C++ are a bit short on the knowledge or are in complete ignorance, of how to use tools that are used by professional programmers daily. These tools like make, gdb, prof/gprof, valgrind/Electric Fence, CVS/Subversion really help you a lot with programming projects and in fact programmers can't imagine doing their work without these tools. You seriously need them for large-scale projects, and even with smaller projects you will notice how helpful they are.

My plan in this post is to give such students a short intro to these tools and places where they can start learning these tools. And as you may have noticed, there is bias towards the Linux/UNIX environment here. That's because it's really a much more powerful environment for programming than Windows. You need tos get good in Linux/UNIX environment if you really want to learn more and better about C, C++ programming.

Note: This book, The Linux Programmers Toolbox , by John Fusco, is a must-have for all those who are looking to do some serious programming in the Linux environment, and covers all the tools I mentioned. It's very well written also.

So let's start with 'make'. When you are writing an application, you will have many source files, that roughly depict how you have broken your app into modules. Now, as will happen almost always, you will need to make changes to some module of your app to get things working, or maybe adding a new feature. Once you have made the changes you will need to recompile. This means you will recompile all your source files (in case you don't know make already) which is a waste of time and CPU resource because you changes only one or a small number of modules in your app. And, so ideally you don't need to recompile the ones you haven't changed. This is where make is so helpful and the importance increases when the size of your application's code increases. The book, C in a Nutshell, by Prinz and Crawford, is also a good resource for learning about gcc, make and gdb. You should try to use GNU make as it is the one used almost in all open-source projects. The page is, GNU make, and has documentation and other relevant information on it. Even if the documentation looks a bit heavy, make sure you do read it every once in a while to know more about the capabilities and intricacies of make, it will help you in the long run.

Now, another very essential tool, 'gdb'. gdb is the GNU debugger. For those of you who still do the debugging by using print statements, it's important you know how to use a debugger because a debugger can save you a lot of time and labour. That's because debuggers will display the values variables are having at any point in the code and so you don't have to guess which variable values to check through print statements, removing and re-writing print statements in your code again and again. Also, you can put breakpoints anywhere and let a particular section of the program run to get an idea of what's going on. Once again, the book C in a Nutshell, is a good place to learn gdb and once again the GNU page manual, gdb, is the authoritative source.

Profilers become important when you want to improve the efficiency of your code. You need to identify the hotspots in your code, that is, the portions of your code which take up most of the execution time. Then you can think about why it's taking that much time, and try to substitute better algorithms. prof, gprof are some common profilers available on the Linux/UNIX systems. You can learn about gprof from this great doc, GNU gprof, by Jay Fenlason and Richard Stallman. This SUN doc, is also a very good one.
Let's move on to memory debuggers. Electric Fence is a memory debugger that triggers a program crash when the memory error occurs, so a debugger like gdb can be used to inspect the code that caused the error. You can learn about eFence (as it is called) on this page by the author of the software, Bruce Perens. He also points to some tools that are better than eFence, however eFence is simpler and a good starting point. 'valgrind' is actually a suite of tools that can automatically detect many memory management and threading bugs, and profile your code in detail. valgrind emulates a CPU and so really slows down your program. You can do some tuning to get a bit improved runtime with valgrind. It's heavy-weight compared to less memory-demanding tools like Purify. valgrind consists of five tools, memcheck (a memory debugging tool), cachegrind (a profiling tool which provides information on cache hit-miss and branch prediction events), callgrind (a tool that shows the call relationships and costs), massif (a space profiling tool which provides information on parts of your code that allocate memory) and helgrind (a debugging tool for threaded programs). You can download valgrind from the official site, and also find the very detailed and good manual there. Again, the manual may look heavy but you should read it.

Well, all the above tools help you with the programming logic and builds. You also need a good tool to manage your code when you are working on a considerable sized project, since you will be revising your code and you need versions of the code so that you can fall back to a code that worked. Also, in the case where you are working in a team a tool is needed that can provide safe access to code to the programmers in team, that is, one person's edits are not interrupted by other and everyone gets latest version of code. In a nutshell, you need a verison control system, like RCS, CVS, Subversion etc. RCS is probably the oldest, CVS is the most tried and tested and Subversion is the newer one with a set of exciting new functionality not in CVS. In the beginning, stages it really won't make a difference which one you pick but eventually you should use CVS or newer alternatives like Subversion. The official Subversion book is a good place for learning Subversion. Some good places to learn CVS are the cvshome.org archive, the Utah University page.

Ok, so with that I end my intro to these tools. I hope I have sparked some interest in some of you and you will go and try using these tools. And believe me, you should learn and use them because they are really necessary when you work on bigger projects. You will save a lot of time and improve your skills. Plus you will feel more like a professional programmer and that's cool, aint it ? ;-)

Wednesday, November 21, 2007

Object Oriented Programming in C - Proof of Concept (Part 2)

Explanation of Code in the first part

Let us now try to understand the C code that was put in the first part of this post. The files new.h and class.h are files that will be common for any user-defined objects (i.e. stacks, queues, complex number or any class that you would like to implement in C). The purpose of new.h is that it declares two functions new and delete that will be used to create and destroy, respectively, any type of objects. The declaration of new tells us that its first argument is a pointer to the type of object that is going to be created. The ellipsis indicates that it can take a variable number of arguments. The arguments will be fetched and passed to the constructor function (here Stack_ctor) of the particular object. Now, there are still some issues like multiple constructors but believe me, that can be handled. I haven't given the implementation of new or delete as I want to convey to you the idea and not bog you down with the details. delete just accepts the pointer to the object to be destroyed, calls the object's destructor (here Stack_dtor) and finally frees the pointer to the object. Yes, we do not have the facility of automatic destruction like the one provided in C++, this is a limitation, you need to call delete explicitly.

Now for class.h, this contains a structure Class, which is nothing but a container for information common to any object. It is something similar to the Object class in Java from which all objects are derived. It contains the size of the object, and then four function pointers. These are for the constructor, destructor, clone and differ functions (see comments for clone and differ functions, they don't affect much the discussion here). Every object is now going to have a pointer to this Class structure (and more importantly, it is going to be the first member of every object, since it gives us an interface to access the constructor, destructor functions of any object).

Now, the header file stack.h, contains a void pointer named Stack. The user needs to be know this header file only for his task. The pointer Stack points to information represented by the structure Class. Later when we allocate an object using new, new will copy this information into the object and then call the object's constructor (here Stack_ctor). Keeping Stack a void pointer does not reveal any details to the user. Then, there are prototypes for the push and pop functions. Yes, you can point out that the void pointer arguments cannot be checked at compile time for the correct type. I have seen some compilers do that for the void pointers but yes this cannot be taken to be a standard behaviour. Proper runtime checks can be done with graceful exit in case of error.

Now, coming to the implementation of the stack in the file stack.c. First we see a structure Stack declared at the top. This structure holds the information generic to every object (the const void pointer class points to the Class structure for this object, this pointing is accomplished by the new function) and it may also hold some variables. Then we have the variables declared with static storage type (this is done to get the effect of private variables in classes in object-oriented languages, same can be done for functions). Next come definitions for the constructor, destructor, clone and differ functions for the stack. Finally we make an instance of the Class structure, _Stack, and then make the our pointer Stack from stack.h file to point to it. Later, new will use the pointer Stack to carry out complete initialization as I described earlier. The file ends with definitions for push and pop functions.

Monday, November 19, 2007

Object Oriented Programming in C - Proof of Concept

Hi,
I believe that the title of this post will come as a surprise to quite a few people in India (I don't know what is the situation outside). The major reason being that probably none of the books in the market on C programming, reveals that this is possible. Now, most people follow the textbooks and rarely try to question what the author is trying to teach them. If the author castigates C for something and praises C++/Java (your OO supporting language here), it is taken for granted, without ever questioning if what the book says is really correct (I mean things the authors say are problems with C or cannot be done in C).

What I want to say is that there are a lot of biased programming texts in the market which do not the convey the true picture. C is their favourite scapegoat when they teach (?) object-oriented programming. Object-Oriented programming at its core is nothing more than a set of best practices, it is not a silver bullet. Any language that supports OO well is called object-oriented, C does not support it very well hence it is not called so. That does not mean you can't do it, it only requires true skill and solid knowledge of the concepts.

Now we will see how to construct the equivalent of class in C. Since class is the thing from where distinction starts between C and OO languages, this should be a convincing proof of concept. Let's put down the main (or you might say basic) features of the class construct and try to get the equivalent in C.
  • A class contains variables (state) and methods/member functions that operate on the state.
  • A class provides you with data encapsulation so that only those methods that need to access the state of class and change it are allowed to do so.
  • A class has constructor method(s) which allow for safe initialization.
  • A class has a destructor that allows for reclamation of memory when it is not to be used again.
For the demo, let us take a simple class that represents a stack. The stack is being implemented using an array.

class Stack {
char *symbols; // pointer to a character array containing the symbols (single chars) in the stack
int top; // top of stack index
int max_size; // maximum size
public:
Stack(int size); // constructor
~Stack( ); // destructor

void push(char symb);
char pop( );
};

Here's the C equivalent. However, I must first point out that much of the following has been taken from the ebook by Axel-Tobias Schreiner, ooc.pdf, from where I learned this. There a couple of pages that point out an altenative and less frightening method to use object-oriented techniques in C. I will be listing them soon.

Header File: new.h

/* methods for creating and destroying any object */
void *new (const void * type, ...);
void delete (void * item);

/* methods common to all objects */
void *clone (const void *self);
int differ (const void *self, const void *other);
size_t sizeOf (const void *self);

Header File: class.h

struct Class {
size_t size;
void * (* ctor) (void * self, va_list * app);
void * (* dtor) (void * self);
void * (* clone) (const void * self);
int (* differ) (const void * self, const void * b);
};

Header File: stack.h

extern const void *Stack; /* the ADT representation for Stack */

void push (void *, char);
char pop (void *);

Implementation of Stack: stack.c

#include "class.h"
#include "stack.h"

struct Stack {
const void *class; /* this should be the first member of the structure always */
/* can put data that is publicly accessible here */
};

/* Data Encapsulation provided by giving the following variables internal linkage in this file,
only functions in this file can access and modify these variables directly */
static char *symbols;
static int top;
static int max_size;

static void *Stack_ctor (void *_self, int size) { ... } /* the constructor function */
static void *Stack_dtor (void *_self) { ... } /* the destructor function */
static void *Stack_clone (const void *_self) { ... } /* this function completely copies one object to other */
static void *Stack_differ (const void *_self, const void *other) { ... } /* this function can check if two objects are the same */

/* initialize the generic Class structure with function pointers specific to the object */
static const struct Class _Stack = {
sizeof(struct Stack),
Stack_ctor,
Stack_dtor,
Stack_clone,
Stack_differ
};
const void *Stack = &( _Stack );

void push (struct Stack *, char symb) { ... }
char pop (struct Stack *) { ... }

User Code

#include "stack.h"
#include "new.h"

int main (void)
{
void *mystack = new (Stack, 20);
char popsymb;

push (mystack, 'X');
popsymb = pop (mystack);
delete(mystack);
return 0;
}

To keep it easier, I have divided this topic into more than one posts. The explanation of above C code comes in the next part of this topic.