Difference between revisions of "Short Notes on C/C++"

From PaskvilWiki
Jump to: navigation, search
Line 102: Line 102:
  
 
If your library needs for it's work to be used together with some other shared/dynamic library, you need to include <tt>-Wl,-export-dynamic</tt> option when creating the object file, so that linker exports all of the symbols, making it clear what all needs to be added for the library to work properly in the program that uses your library.
 
If your library needs for it's work to be used together with some other shared/dynamic library, you need to include <tt>-Wl,-export-dynamic</tt> option when creating the object file, so that linker exports all of the symbols, making it clear what all needs to be added for the library to work properly in the program that uses your library.
 +
 +
== Singleton ==
 +
 +
=== Traditional Approach ===
 +
 +
<pre>// Singleton.h
 +
 +
class Singleton
 +
{
 +
private:
 +
    Singleton() { }
 +
    Singleton(const Singleton&) { }
 +
    Singleton& operator=(const Singleton&) { }
 +
    ~Singleton() { }
 +
    static Singleton* inst;
 +
 +
public:
 +
    static Singleton* instance();
 +
 +
};</pre>
 +
 +
<pre>// Singleton.cpp
 +
 +
#include "Singleton.h"
 +
 +
Singleton* Singleton::inst = NULL; 
 +
 
 +
Singleton* Singleton::instance()
 +
{
 +
    return inst ? inst : inst = new Singleton;
 +
}</pre>
 +
 +
=== Stack-based Singleton ===
 +
 +
I usually prefer this version over the dynamically allocated one, as the destructor will be called (at some point in time), and allows you to free up all resources obtained during the lifetime - esp. close files, sockets, etc.
 +
 +
<pre>class Singleton
 +
{
 +
private:
 +
    Singleton();
 +
    Singleton(const Singleton&);
 +
    Singleton& operator=(const Singleton&);
 +
    ~Singleton();
 +
 +
    // ...
 +
 +
public:
 +
    static Singleton& instance()
 +
    {
 +
        static Singleton inst;    // constructed on the first call
 +
        return inst;
 +
    }
 +
 +
    // ...
 +
 +
};</pre>

Revision as of 06:00, 24 December 2012

How to clean up after child thread

Even when the child thread shuts down gracefully - i.e. the thread's function returns, or the thread calls pthread_exit() - there might still be a memory leak due to the thread data allocated during the call to pthread_create().

There are 3 options to handle this:

  • stop the thread from the creator thread using pthread_cancel(),
  • wait for the thread to shut down gracefully, and then pthread_join() with the thread (yes, "join with the stopped thread"); this call returns immediately, and frees up thread's resources,
  • have the thread clean up on its own, by pthread_detach()-ing the thread.

Non-blocking IO using sockets

To get a non-blocking IO, you can

  • set the socket to non-blocking:
// for fcntl()
#include <unistd.h>
#include <fcntl.h>
// for ioctl()
#include <sys/ioctl.h>

int set_nonblocking(int fd)
{
    int flags;
#if defined(O_NONBLOCK)
    if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
        flags = 0;
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
    flags = 1;
    return ioctl(fd, FIOBIO, &flags);
#endif
}
  • or, you can use MSG_DONTWAIT as flags in the calls to recv(), recvfrom(), send(), and sendto().

Or both... can't hurt. ;-)

Shared Libraries on Linux+GCC

Shared libraries on Linux typically name linker name, soname, and real name.

The linker name is typically "libtest.so". The soname is linker name with version, typically "libtest.so.1", and the real name is the name of the file, typically "libtest.so.1.0.3".

In reality, the "libtest.so.1.0.3" would be the actual file, with two links:

libtest.so.1 -> libtest.so.1.0.3
libtest.so   -> libtest.so.1

Example

Here's an example of "test_so" library - .h and .c files, how to build and link the .so file, and using this library from Python using ctypes.

test_so.h

#ifndef __TEST_SO__
#define __TEST_SO__

int test_so_string(const char* str);
int test_so_int(int i);

#endif//__TEST_SO__

test_so.c

#include "test_so.h"
#include <string.h>

int test_so_string(const char* str)
{
    return strlen(str);
}

int test_so_int(int i)
{
    return -i;
}

Compiling and Linking

gcc -fPIC -O3 -c -Wall test_so.c
gcc -shared -Wl,-soname,libtest_so.so.1 -o libtest_so.so.1.0.0 test_so.o -lc

Now, you can create also the "upper links":

ln -s libtest_so.so.1.0.0 libtest_so.so.1
ln -s libtest_so.so.1 libtest_so.so

Using from Python - test_so.py

import ctypes
lib = ctypes.CDLL("./libtest_so.so")

print "int -> int fcall works" if lib.test_so_int(1) == -1 else "int -> int fcall DOESN'T WORK!"
print "string -> int fcall works" if lib.test_so_string("hello there!") == 12 else "string -> int fcall DOESN'T WORK!"

will output:

$ python test_so.py 
int -> int fcall works
string -> int fcall works

See ctypes library for more info.

Notes

If your library needs for it's work to be used together with some other shared/dynamic library, you need to include -Wl,-export-dynamic option when creating the object file, so that linker exports all of the symbols, making it clear what all needs to be added for the library to work properly in the program that uses your library.

Singleton

Traditional Approach

// Singleton.h

class Singleton
{
private:
    Singleton() { }
    Singleton(const Singleton&) { }
    Singleton& operator=(const Singleton&) { }
    ~Singleton() { }
    static Singleton* inst;

public:
    static Singleton* instance();

};
// Singleton.cpp

#include "Singleton.h"

Singleton* Singleton::inst = NULL;  
  
Singleton* Singleton::instance()
{
    return inst ? inst : inst = new Singleton;
}

Stack-based Singleton

I usually prefer this version over the dynamically allocated one, as the destructor will be called (at some point in time), and allows you to free up all resources obtained during the lifetime - esp. close files, sockets, etc.

class Singleton
{
private:
    Singleton();
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);
    ~Singleton();

    // ...

public:
    static Singleton& instance()
    {
        static Singleton inst;    // constructed on the first call
        return inst;
    }

    // ...

};