A Developer's Diary

Feb 28, 2008

AIX - Tuning process memory size limits

When a process runs out of memory, the process often ends. On AIX systems, the system error log might indicate that the process ended due to memory allocation failure. Use the following command to display the error log

errpt -a | more


On UNIX systems, each user can either inherit resource limits from the root user or have specific limits defined. The most useful setting to use for the process size limits is unlimited. That way, the system process size limits are defined to allow the maximum process growth.

On AIX systems, the number of data segments that a process is allowed to use also limits the process memory size. The default number of data segments is 1. The size of a data segment is 256 MB. Data segments are shared for both data and stack. The maximum number of data segments a process can use is 8

On AIX, the number of segments that a process can use for data is controlled by the LDR_CNTRL environment variable. It is defined in the parent process of the process that is to be affected. For example, the following example defines one additional data segment:

export LDR_CNTRL=MAXDATA=0x10000000


Read more ...

Feb 23, 2008

Print Hello, World without using semicolon

Not used practically, but asked very frequently by the interviewers.

#include <stdio.h>

int main(){
if(printf("Hello, World\n")){}
while(!printf("Hello, World\n")){}
switch(printf("Hello, World\n")){}
return 0;
}

Read more ...

Feb 18, 2008

Symmetric Cipher

Symmetric Ciphers
Functions Provided: Encryption and Decryption.

They are known as Symmetric because both the sender and the receiver share the same key to encrypt and then decrypt the data. The main function is to provide Confidentiality.
e.g. Say Alice needs to send Bob a confidential document. She would encrypt the document using a symmetric cipher and a key and send it to Bob. Anybody looking at the message enroute to Bob will only see sequence of bytes. Bob on receiving the message will use the same key and the decrypt function of the symmetric cipher used by Alice to produce the original message. Few Symmetric Ciphers are: rotate cipher, Caeser cipher etc.









Disadvantages:
1. The key has to transferred to Bob through a separate communication channel which has to be secure. Then the question arises, if we have a secure communication channel, then why not send the document through that secure channel.
2. If Alice needs to send the document to 100 people, then she would have to use 100 different keys and encrypt the message 100 times and share them across.


Read more ...

Direct Initialisation and Copy Initialisation

How many ways are there to initialize a variable?

1. MyType type;

Here the variable type is initialised using the default ctor MyType::MyType();

2. MyType type();

This looks like a variable declaration, but it's a function declaration for a function type that takes no parameters and returns a MyType.

3. MyType type(u);

This is direct initialization. The variable type is initialized using MyType::MyType(u);

4. MyType type = u;

This is copy initialization and the variable type is always initialized using MyType's copy ctor. Even though there is an '=' sign, this is a copy initialization and not an assignment.

The form MyType type(u) should be preferred. It always works where 'MyType type = u' works and has other advantages e.g (It can take multiple parameters)

Code

/* Example1.cpp */
#include <iostream>
#include <string>
#include <iomanip.h>
class MyType{
private:
int age;
std::string name;
public:
MyType():age(10),name("pankaj"){
std::cout << "\nCalling Constructor 1\n";
}
MyType(int age, std::string str):age(age), name(str){
std::cout << "\nCalling Constructor 2\n";
}
MyType(MyType &t):age(t.age), name(t.name){
std::cout << "\nCalling Constructor 3\n";
}
void show(){
std::cout << "\nName is = "<<name;
std::cout << "\nAge is = "<<age;
std::cout << endl;
}
};

int main(){
MyType type;
type.show();
MyType t(type);
t.show();
MyType b(50, "Anky");
MyType a = b;
a.show();
}


Output:
$ ./a.exe

Calling Constructor 1

Name is = pankaj
Age is = 10

Calling Constructor 3

Name is = pankaj
Age is = 10

Calling Constructor 2

Calling Constructor 3

Name is = Anky
Age is = 50

Here, MyType a = b; also calls the Constructor 3

Code

/* Example2.cpp */
#include <iostream>
#include <string>
#include <iomanip.h>
class MyType{
private:
int age;
std::string name;
public:
MyType():age(10),name("pankaj"){
std::cout << "\nCalling Constructor 1\n";
}
MyType(int age, std::string str):age(age), name(str){
std::cout << "\nCalling Constructor 2\n";
}
//MyType(MyType &t):age(t.age), name(t.name){
std::cout << "\nCalling Constructor 3\n";
}
void show(){
std::cout << "\nName is = "<<name;
std::cout << "\nAge is = "<<age;
std::cout << endl;
}
};
int main(){
MyType type;
type.show();
//MyType t(type);
//t.show();
MyType b(50, "Anky");
MyType a = b;
a.show();
}


Output:
$ ./a.exe

Calling Constructor 1

Name is = pankaj
Age is = 10

Calling Constructor 2

Name is = Anky
Age is = 50

Here MyType a = b; works even when Constructor 3 is commented out because a default copy constructor is created for you when you don't specify one yourself. In such case, the default copy constructor will simply do a
bitwise copy for primitives (including pointers) and for objects types call their copy constructor. If in the later case, a copy constructor is not explicitly defined then, in turn, a default copy constructor will be implicitly created.

Read more ...

Feb 17, 2008

80-20 Rule

According to 80-20 Rule: Look for that 20% of the code where your program spends 80% of it's time

e.g. The HTTP specification is a 100 page document that describes all possible HTTP requests that a web server must handle.Most of the HTTP requests that traverse through the web are very simple. They contain only a small subset of the possible HTTP headers that a request can possibly contain.

Since Microsoft and Netscape have a dominating share of the browser market, all you need to do is peek at the request headers sent by these two browsers. This is yet another manifestation of the 80-20 rule—20% of your possible inputs will occur 80% of the time. An efficient use of programmer resources is to tune those 20% of the request types that appear 80% of the time.
The HTTP Accept header is part of an HTTP request. It specifies what document formats are acceptable to the browser. The HTTP specification allows for the Accept header to have any combination of upper and lowercase. When you read a string token and want to determine if it is the Accept header, it is not enough to perform

memcmp("Accept:", header, 7)

We need to perform a case-sensitive string compare. We implemented a home-grown version for a casesensitive string-compare:

int memCaseCmp(char*,char*, int) {...}

To be HTTP compliant, the correct action should be

Code
if ( 0 == memCaseCmp("accept:", header, 7) )
{
// This is the Accept header
}

However, memCaseCmp() is not cheap. It needs to uppercase both strings and then call memcmp(). This is where our domain expertise must come into play. Like we said, Microsoft and Netscape have a commanding share of the browser market. The Accept header they send happens to be "Accept:". This is only one of the many upper- and lowercase combination that HTTP allows, but it is the one we are going to receive 95% of the time, so it is the one we care about. The following test tries to take advantage of that:

Code
if ( (0 == memcmp("Accept:", header,7)) || // An intelligent // gamble... (0 == memCaseCmp("accept:", header, 7))) { // This is the Accept header }

In 95% of the inputs, the memcmp() test is going to succeed, and we will never call the more expensive memCaseCmp().

Read more ...

Feb 16, 2008

Synthesised Default Constructor

If we do not explicitly define constructors, then the compiler will generate the default constructor for us. The compiler-created default constructor is known as Synthesised Default Constructor.

It initializes each member using the same rules as are applied for variable initializations. Because the synthesised constructor does not automatically initialise the members of build-in type, we have to define the default Constructor explicitely. Bugs due to uninitialised variables can be hard to find.

Unitialised variables cause Run-Time problems as no compiler can detect all uses of uninitialised variables.

Read more ...

Feb 4, 2008

Finding dependent libraries on Aix

Finding dependent libraries on AIX.

Method 1.
This is a small dlopen test program "dltest.cpp"

//File: dltest.cpp

#include <stdio.h>
#include <dlfcn.h>

int main()
{
    char str[20] = {0};
    printf("\nEnter path to the Library to be loaded = ");
    scanf("%s", str);

    void *libhandle = dlopen(str, RTLD_LAZY);
    if(NULL == libhandle)
    {
        printf("\nUnable to load library. Error: %s\n", dlerror());
    }
    else
    {
        printf("\nSuccessfully loaded library %s\n", str);
    }

    return 0;
}

Compile the above program using:
xlC_r -brtl -o out dltest.cpp

Executing the file ./out will give the dlerror() output and the missing dependent libraries.

Method 2.
A dirty way to search.

ldd filename


It will not list the libraries which are present. It simply displays "Cannot Find" all libraries which are dependent and not found.
More conveniently

truss ldd somefilename.so >> output.txt 2>&1

Check the output.txt and search for libs which are not there.
Read more ...