C++ - Optional function arguments / parameters

10. May 2012 13:00

 

This is a quick tip in C++ for providing support for optional parameters on functions. This works because when a function is declared in C++ it can be given a default value and when that paramater is missing from the calling function the compiler will automatically add it during compile time and pass the default value.

 

Heres a simple example of this.

 

 

#include <stdio.h>

bool func(bool val = false) {
    return val;
}


int main(int argc, char **argv) {

    printf("%d\n", func());
    printf("%d\n", func(false));
    printf("%d\n", func(true));

    return 0;
}

 

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


Doing for loops in bash

9. May 2012 23:21

 

It can be commonly known that you can do for loops in bash by doing something like for i in * ; do echo $i ; done or some such. This will loop for every file in the current directory. Though typical for loops for a specific number range can be a little more difficult since you need to form the data to be able to execute the loop.

 

To get a simple for loop to work we can copy python's for i in range(x, y): type of loop since the bash for loop is exactly the same as this. Both bash / python perform a for each loop around a list of data items rather than the traditional for loop with a counter. This can be used to our advantage since all you need to do is create a small program that generates this data lists.

 

The following c program does this.

 

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

void print_usage(FILE *fp, char *app) {
    fprintf(fp, "Usage: %s <start number> <end number>\n", app);
    fprintf(fp, "\n");
}

int main(int argc, char **argv) {
    int a = 0, b = 0;
    int i;

    if (argc < 3) {
        print_usage(stderr, argv[0]);
        exit(EXIT_FAILURE);
    }

    a = atoi(argv[1]);
    b = atoi(argv[2]);
    
    if (a >= b) {
		int tmp = a;
		b = a;
		a = tmp;
    }

    for(i=a;i<=b;i++) {
        printf("%d\n", i);
    }

    return 0;
}

All you need to do is put the program above into a c file and compile it with gcc (gcc -Wall range.c -o range) and place the executable on the path (eg in $HOME/bin). Then you can do for loops in the bash shell the following way.

 

for i in `range 0 20` ; do echo $i ; done

The above will of course produce the output of 0 to 20 on the terminal when run.

 

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


C/C++ - Generate a random number

19. April 2012 21:57

 

This is a short example for generating a random number in C/C++. It is actually easy to do. In this case we can produce a random number between 0 and 10 and print it out.

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


int main(int argc, char **argv) {

	srand(time(NULL));

	for(int i =0;i<10;i++) {
		int r = rand() % 10;
		printf("%d\n", r);
	}

	return 0;
}

 

The solution above will only work for generating a number from 0 to RAND_MAX which is typically 32768.

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


Floating point comparisons don't work. Don't event attempt them

12. April 2012 22:23

 

This started because somebody discovered and issue with php. Which turns out to also pop up in other languages like php, javascript and of course python. These magic numbers happen to be an edge case for a double precision floating point number. So it actually happens in all languages. Simply put the number is large enough to start dropping the least significant digits.

 

One of these numbers happen to be 9223372036854775807.0

 

Here is an example of what the problem is.

 

>>> 9223372036854775807 == 9223372036854775808
False
>>> 9223372036854775807.0 == 9223372036854775808
True

 

Obviously you would think that the 2nd should also equal false. However in a floating point number they are actually converted to the same number. So of course they actually appear to be equal. We can show this by doing the following.

 

>>> a = 9223372036854775807.0
>>> b = 9223372036854775808.0
>>> a == b
True
>>> print a
9.22337203685e+18
>>> print b
9.22337203685e+18

 

As you can see the numbers are actually the same. However when you try to compare them some other ways they also break when trying to compare when forcing the type to an int like this.

 

 

>>> int(9223372036854775807) == int(9223372036854775808)
False
>>> int(9223372036854775807.0) == int(9223372036854775808)
True
>>> int(9223372036854775807.0) == 9223372036854775808
True
>>> 9223372036854775807.0 == int(9223372036854775808)
True

Like this

 

 

>>> print int(9223372036854775807)
9223372036854775807
>>> print int(9223372036854775807.0)
9223372036854775808

 

 

However this particular problem does not apply to python alone it does actually apply to anything that is using the standard ieee 64 bit floating point since it is actually impossible to represent the number 9223372036854775807.0 to it gets rounded to the nearest floating point number that happens to be 9223372036854775808

 

We can prove this because it's also acts this way in a C compiler.

 

 

#include <stdio.h>

int main(int argc, char **argv) {
        double a = 9223372036854775807.0;
        double b = 9223372036854775808.0;

        if (a == b)
                printf("True\n");
        else
                printf("False\n");

        return 0;
}

 

And if you take it down to assembler it will also show that it is happening there. However if you look at the raw data in the exe file you will also see that it has actually already truncated the number 9223372036854775807.0 to the same as the other number 9223372036854775808.0

 

Just to make it stick a little more the following is exactly the same issue!

 

>>> a = 9999999999999999.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
>>> b = 9999999999999999.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
>>> a == b
True

 

Its floating point. Don't attempt to compare them ever to be equal to each other! It doesn't work with large numbers because there is not enough accuracy to store the information.

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


Using gdb to debug a core file

5. April 2012 08:00

 

The gnu debugger (gdb) is probably the best tool for looking into core files. It also isn't overly complex to use to get some basic starting information. So this is a quick guide to getting some debug information eg variable's and stack traces from a core dump which is formed when an application crashes in linux.

 

If an application crashes and doesn't produce a core file it is probably because of the limit settings you can check and enable core dumps by using the following "ulimit -c" if it outputs a 0 it will not produce a core. You can use "ulimit -c unlimited" to make the core dump file size unlimited. Be aware though that if you have a lot of crashes it can use a significant amount of disk space.

 

Let start with finding out what made a core file in the first place. In order to debug it at all you need to know exactly what program crashed. You can determin this using the following command.

 

cat core |strings |grep -E '^_='
_=./willcore.exe

 

In this case the "./willcore.exe" made the core dump. Another way to find out what core'd is to use gdb. The example is below

 

gdb --core core

Core was generated by `./willcore.exe'.
Program terminated with signal 11, Segmentation fault.
#0  0x080483d4 in ?? ()
(gdb)

 

Something to notice at this point is that is shows where the last execution point was. In this case it was running at memory location 0x080483d4. However since there are no debugging symbols loaded in gdb yet it shows ?? because it cannot translate the raw address to a function.

 

You can get gdb to load the executable and debugging symbols (assuming they are compiled into the executable) using the "file" command. I have also added the "bt" command to produce a back trace so show the execution stack.

 

 

(gdb) file ./willcore.exe
Reading symbols from /home/james/CVS-Root/linux/misc/willcore.exe...done.
(gdb) bt
#0  0x080483d4 in main (argc=1, argv=0xbf877ef4) at willcore.c:8

 

In the example above the symbols now resolve and will show a lot more information. If they do not show after loading the executable into gdb it will be a problem with debugging symbols. You will need to go and compile the program with debugging switched on eg the "-ggdb" flag in gcc and g++.

 

Now that things are loaded you can move between stack frame's using "frame <number>" where number is the part beside the # in the stack output and you can also print and inspect other parts of memory as well as list the source code from the program assuming the source still exists in the original location that it was compiled from.

 

 

(gdb) p argc
$1 = 1
(gdb) p argv[0]
$2 = 0xbf87988c "./willcore.exe"
(gdb) p argv[1]
$3 = 0x0
(gdb) list
1
2
3       #include <stdio.h>
4
5       int main(int argc, char **argv) {
6               char *tmp = 0;
7
8               *tmp = '0';
9
10
(gdb) p tmp
$4 = 0x0

 

Note: the above example shows how to produce a core file by dereferencing a null pointer in c which in its self can be useful to fore a core dump which is what I used for this tutorial.

 

As a final example the following will dump all the stacks from all threads that were running in a process at the time it crashed. Though in the sample program there only is one thread. In a large application this could provide several pages of output.

 

 

(gdb) thread apply all bt

Thread 1 (Thread 12519):
#0  0x080483d4 in main (argc=1, argv=0xbf877ef4) at willcore.c:8
(gdb)

 

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