C++ - Why you need a copy constructor

29. March 2013 10:29

 

In C++ you may come across an issues where you need to use a copy constructor. This is because when a class is assigned from one variable to another it has to copy the values across. If we are dealing with pointers that are inside the class then the pointer will be copied. So this can create and issue if the pointer is deallocated in the destructor. Since now there is two copied of the same pointer which is going to be deallocated twice. This will result in a common issue such as a double free.

 

In this short program you can see the effect here that will cause a double free. In this case I am using "malloc" to keep the example short. The following program will crash when the main function returns as it will call free from the destructor twice on the same pointer value.

 

 

class MyClass {
    public:
        char *buf;
		size_t buf_len;

        MyClass(size_t len) {
            printf("Alloc\n");
			buf_len = len;
            buf = (char *) malloc(len * sizeof(buf));
        }

        ~MyClass() {
            printf("Free\n");
            free(buf);
        }
};


int main(int argc, char **argv) {
    MyClass x = MyClass(4096);
    MyClass y = x;

    return 0;
}

 

 

To get another the issue above in C++ we must use a copy constructor which will allow us to override the default functionality when the class is copied in order to allocate and copy the contents of the buffer and a new pointer which will completly seperate the source class from the new class that is being assigned.

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class MyClass {
    public:
        char *buf;
		size_t buf_len;

        MyClass(size_t len) {
            printf("Alloc\n");
			buf_len = len;
            buf = (char *) malloc(len * sizeof(buf));
        }

        ~MyClass() {
            printf("Free\n");
            free(buf);
        }
        
        MyClass(const MyClass &source)
        {
        	buf_len = source.buf_len;
        	buf = (char *) malloc(buf_len * sizeof(buf));
        	memcpy(buf, source.buf, buf_len);
        }
};


int main(int argc, char **argv) {
    MyClass x = MyClass(4096);
    MyClass y = x;

    return 0;
}

 

E-mail Kick it! DZone it! del.icio.us Permalink


C++ - Boost Optional

27. March 2013 17:21

 

Using boost::optional can be an advantage in certain situation. In C++ it effectivly works by being able to turn any datatype into a nullable value. It works much the same way as returning a null pointer to an object but without using a pointer. Instead this will work by being able to return an object which may or may not valid.

 

It is typically used to return a value from a function where the function may fail in certain situations. If you attempt to use the optional value which has not been set it will fail and the program will abort. This of course is also useful for debugging in order to catch issues sooner rather than later by accessing various variable that may not have valid values.

 

It can of course also be used to pass optional paramaters to functions where you may not want to use operator overloading.

 

Here is an example of it converting an string to an int which will obviously fail on one of the strings.

#include <stdio.h>
#include <string>

#include <boost/optional.hpp>

boost::optional<int> func(const std::string &str)
{
        boost::optional<int> value;
        int tmp = 0;

        if (sscanf(str.c_str(), "%d", &tmp) == 1)
                value.reset(tmp);

        return value;
}

int main(int argc, char **argv)
{
        boost::optional<int> v1 = func("31245");
        boost::optional<int> v2 = func("hello");

        if (v1)
                printf("%d\n", v1.get());
        else
                printf("v1 not valid\n");

        if (v2)
                printf("%d\n", v2.get());
        else
                printf("v2 not valid\n");

        return 0;
}
The output of the above is
31245
v2 not valid
E-mail Kick it! DZone it! del.icio.us Permalink


Linux - What and how to kill a zombie process

1. March 2013 10:12

 

What is a zombie?

 

A zombie process is simply a process that has exited but its parent has not yet read the processes exit code. Since the process has exited it does not have any open files or uses any memory in fact the only resources it is using is a entry in the task list. So in most Linux systems will mean that it is using around 4k-8k of memory.

 

Until the parent process reads the exit code the zombie will exist. Typically this points to a software bug in the parent process or an issue that caused the child (which is now the zombie) to exit unexpectedly. Which would also point to a bug or issue in the program. In either case the parent process should have actually dealt with the error an acted on it to read the exit status of the process which will clean up the zombie process and allow it to exit.

 

Why is there any issue?

 

Since the program isn't really using any resources it really doesn't cause any issues. However if you have a lot of zombie's being generated inside a system due to a bug in the software it will cause an issue because it is still running as a process and sooner or later you will hit the limit of the maximum number of processes permitted to run in the system. If this limit is reached you will not be able to start any more processes. This means you won't be able to run commands from the command line any more.

 

Why does kill now work on the zombie process?

 

Kill simply does not work on a zombie process since it is in fact already "dead"

 

How to kill it?

 

Since the issue really exists in the parent process the solution is to remove the parent process either by killing it or shutting it down. This will cause the child "zombie" processes to get a new parent process which will be the parent of the parent.

 

If you are working in a complex system you may need to kill several parent process in order to eliminate the zombies until the zombies get a parent process that will read the exit code from the processes which will cause the zombie process to be remove.

 

 

Hint: if you use the command "ps axfu" the "f" in the argument list will print the output as a tree which will make finding the parent somewhat simpler.

E-mail Kick it! DZone it! del.icio.us Permalink


C - Some Simple Examples of using strcat

16. February 2013 11:06

 

This post shows some simple example of using strcat to join two strings together in C

 

The msot common example you will find on the internet will work by just making an array that is "big enough" to store both the strings. However this can create problems when the strings you use are too long so it would need these conditions handled correctly in C. So it probably isn't the best example to use.

 

 

void basic(char *s1, char *s2)
{
	char str[200] = "";
	
	strcat(str, s1);
	strcat(str, s2);
	printf("basic: %s\n", str);
}

 

 

A better example of using strcat is to allocate an array dynamically. In this case on the stack. So this will work slightly better however it can cause a significant amount of stack space to be used and can also cause crashes if the strings are too long. However it will execute very quickly because dynamic allocation of memory on the stack will perform well.

 

 

void better1(char *s1, char *s2)
{
	char str[strlen(s1) + strlen(s2) * sizeof(*s1) + 1];
	str[0] = '\0';

	strcat(str, s1);
	strcat(str, s2);
	printf("basic: %s\n", str);
}

 

 

A much better example of this is to use malloc / free for the allocation of string. This will be slightly slower than the previoud example but will be able to handler much larger strings and much safer to use. It can of course still crash but only if the machine run's out of memory. How ever this error can be handled to prevent it crashing by changing the call to abort() to use proper error handling.

 

 

void better2(char *s1, char *s2)
{
	char *str = malloc(strlen(s1) + strlen(s2) + 1 * sizeof(*s1));
	if (str == NULL)
		abort();
	str[0] = '\0';
	
	strcat(str, s1);
	strcat(str, s2);
	printf("basic: %s\n", str);
		
	free(str);
}

 

Finally this is an example about joining multiple strings so we can just keep making our string longer and longer or join it from multiple different sources. Note that the following code really needs a check around the realloc function to see if it returns NULL. If it does then it should fail by returning the previous pointer. Or call abort because the system has run out of memory.

 

 

char *multiple(char *str, char *s2)
{
	int len;
	char *s;
	if (str != NULL)
		len = strlen(str);
	len += strlen(s2) + 1 * sizeof(*s2);
	s = realloc(str, len);
	strcat(s, s2);
	return s;
}

 

With the above code we can call it in the following way

 

 

char *tmp = multiple(NULL, "Hello ");
	tmp = multiple(tmp, " World");
	tmp = multiple(tmp, " We");
	tmp = multiple(tmp, " Can");
	tmp = multiple(tmp, " Join");
	tmp = multiple(tmp, " strings");
	printf("%s\n", tmp);
	free(tmp);

 

E-mail Kick it! DZone it! del.icio.us Permalink


Debian - Getting sshfs to work

14. February 2013 20:23

 

This is a short guide to get ssh to work on debian. So this should also work with some other linux varients like ubuntu. It can be a very useful tool to be able to access your home directory from a 2nd linux machine or from your raspberry pi. I have been using it so that you can run your normal powerful code editors which the raspberry pi does not have enough resources to run them fast enough.

 

 

To Install / Setup

 

sudo apt-get install sshfs 

sudo addgroup $USER fuse

 

Note: You don't need to add your self to the fuse ground. But it is required if you want to be able to mount / umount the filesystem without root permissions.

 

 

To Use

 

mkdir Raspberry

sshfs <username>@<ip address>:/home/<username>/Raspberry  -o uid=1001,gid=1002 Raspberry

 

 

Note: in the above you should change the uid and gid to your user id and group id. You can look thoose up in the /etc/passwd and /etc/group files on the machine that you are mounting the remote filesystem on.

 

 

To unmount

 

fusermount -u /home/james/Raspberry/

 

 

 

Another useful tip is that it will also work with ssh key authentication so that you do not even require a password or so that you can have it configured to automount on boot using the crontab.

E-mail Kick it! DZone it! del.icio.us Permalink