Create static and shared libraries in Unix

Static Library
Lets first look at how static library can be created and used :

(a) Compile print.c to get an object file :
gcc -c print.c -o print.o

(b) Create a static library (archive) of the object file :
ar rcs libprint.a print.o

According to *nix norms, static library’s name should start with ‘lib’ and have ‘.a’ extension. ar is a unix tool to create, modify and extract from archives.

(c) Now compile main.c and link it statically to the library.
gcc -static main.c -L. -lprint -o statically_linked

$ ./statically_linked
hello world!

Shared Library
One of the most important things to note while creating shared libraries is the object files should be compiled with -fPIC option (position-independent code).

(a) gcc -fPIC -c print.c -o print.o

(b) gcc -shared -o print.o

(c) gcc main.c -o dynamically_linked -L. -lprint

$ LD_LIBRARY_PATH=. ./dynamically_linked
hello world!

Note: Detailed explanation of the above used gcc switches can be found in gcc manual pages.

Singleton : Restrict instantiation of a class to one object

In order to achieve this, first thing which we need to do is make the class’s constructor private, which in turn will not allow any other class (outside) to create an abject of that class directly using the constructor. After this we can just define a getInstance method, which does the required two things:
1. Check how many objects of the class have been created.
2. Depending on (1) return an instance of the class.

Here is the code :

  @file :

class Singleton {
  private static int counter=0;

  private Singleton() { //private constructor
    System.out.println("Object instantiated!");

  static Singleton getInstance() {
    if (counter < 1 ) { // to allow only 1 object creation.
      Singleton inst = new Singleton();
      counter ++;
      return inst;

    System.out.println("Can't instantiate further ..");
    return null;

public class test {
  public static void main(String str[]){
    Singleton ins1 = Singleton.getInstance();
    Singleton ins2 = Singleton.getInstance();
    Singleton ins3 = Singleton.getInstance();

Output :

$ java test
Object instantiated!
Can't instantiate further ..
Can't instantiate further ..

gcc : undefined reference error

A very common compiler error when we try to compile a C++ program using gcc on Linux.

$ gcc 
/tmp/cccP8Jve.o: In function `main': undefined reference to `operator new[](unsigned long)' undefined reference to `std::cout'

Fix :

(a) Use g++ : g++

(b) gcc -lstdc++

Simulating disk-full scenario

Unix-like operating systems provide a number of device files in order to simulate different behaviors. In this article we will focus on simulating a “disk-full” scenario using a special file named /dev/full. Its a special file which always returns an error when an attempt is made to write to this file. Lets try to simulate this through a program :

/* disk-full.c */


int main()
  int fd;
  ssize_t rc;
  char *buf= "hello world!";

  // Open /dev/full for writing.
  fd= open("/dev/full", "w");

  if (fd == -1)
    printf("Error! Couldn't open the file. %d : %s\n",
           errno, strerror(errno));

  /* Now, lets try to write into this file. */
  rc= write(fd, buf, 1);

  if (rc == -1)
    printf("Error! Couldn't write to the file. %d : %s\n",
           errno, strerror(errno));

  return 0;

Output :

Error! Couldn't write to the file. 28 : No space left on device

Besides /dev/full, there are other interesting device files available under /dev, which can help in a multitude of ways.

> hexdump -Cn80 /dev/urandom 
00000000  ee 32 7c 62 97 17 79 33  71 20 d5 2e 82 32 cd 32  |.2|b..y3q ...2.2|
00000010  26 02 b4 75 4e 90 5d 2f  fb 7f 58 d8 9b ba 50 34  |&..uN.]/..X...P4|
00000020  f5 30 2a e0 b1 95 ea a4  0c 92 ef 57 99 0e b1 ec  |.0*........W....|
00000030  a5 78 df 45 39 df 17 02  12 c1 0b dd cc d0 e0 ad  |.x.E9...........|
00000040  fd 65 c8 71 25 e7 1d 71  c9 77 1d 2a 57 78 be 1f  |.e.q%..q.w.*Wx..|

Using Valgrind with GDB

Valgrind is a very powerful tool for detecting & diagnosing memory related issues in a C/C++ program. Sometimes, the task of locating the actual problematic area becomes increasingly tedious if the code base is huge and complex.

Let us now try to debug a small program running under Valgrind using GDB.

/* leaky.c */

int main()
  char *ptr= malloc(100);
  printf("I am a leaky program!\n");
  return 0;

Before we move further, one point to note here is that a process running under Valgrind is actually running on a synthetic CPU provided by Valgrind and hence it cannot be debugged directly using GDB [source]. So, in order to overcome this limitation, Valgrind-3.7.0 introduced ‘gdbserver’, an implementation of GDB remote debugging protocol, using which the process can be debugged.

Step 1 : Start the process under Valgrind with –vgdb=yes & –vgdb-error=0 options

> gcc -g leaky.c

> valgrind --vgdb=yes --vgdb-error=0 ./a.out 
==6148== Memcheck, a memory error detector
==6148== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==6148== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==6148== Command: ./a.out
==6148== (action at startup) vgdb me ... 
==6148== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==6148==   /path/to/gdb ./a.out
==6148== and then give GDB the following command
==6148==   target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=6148
==6148== --pid is optional if only one valgrind process is running

Step 2 : In a different terminal start GDB

> gdb a.out 
GNU gdb Red Hat Linux (6.5-25.el5rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/".

Step 3 : In the same gdb session,

(gdb) target remote | /usr/lib64/valgrind/../../bin/vgdb
Remote debugging using | /usr/lib64/valgrind/../../bin/vgdb
relaying data between gdb and process 6148
[New thread 6148]
[Switching to thread 6148]
0x0000003f10000a60 in ?? ()
(gdb) b main
Breakpoint 1 at 0x4004e0: file leaky.c, line 7.
(gdb) c

Breakpoint 1, main () at leaky.c:7
7	  char *ptr= malloc(100);

And step through the code further..