Dynamic Printf Debugging with GDB

When we debug a program with printf() we have to recompile it whenever we add new printf() statements! Right!?

Wrong!

With gdb we can add printf() statements without recompiling a program and even add them while it is running.

Adding Printfs with GDB

Let’s say we have the following example program that computes the sum of all the elements of an array:

#include <stdio.h>

int main(int argc, char **argv)
{
    int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int n = sizeof(numbers) / sizeof(numbers[0]);
    int sum = 0;

    for (int i = 0; i < n; i++) {
        sum += numbers[i];
    }

    printf("Sum of array: %d\n", sum);

    return 0;
}
Continue reading “Dynamic Printf Debugging with GDB”

Making the most of your Shells History on Linux and macOS

Modern UNIX shells like bash (default on Linux) and zsh (default on macOS) keep a history of all the commands you enter. The easiest way to access this history is by pressing the up and down cursor keys to browse through the last commands.

But this is only the tip of the iceberg. There are many more powerful history features that are easy to overlook. Learning them and making them second nature will help you to become much faster with a shell.

Viewing the History

The full history can be printed with the history command:

$ history
100 cd
101 vim file.txt
102 ls
103 mount
104 cat /etc/fstab
$
Continue reading “Making the most of your Shells History on Linux and macOS”

Getting started with GDB

Most programmers prefer to write code over debugging it. Unfortunately, code breaks a lot more often than we would like and it often breaks in situations that are hard to debug. Therefore, an essential skill as a programmer is to know how to debug your code (and that of others).

When facing our first bug we all start out with what is called printf debugging. That means we add lines of code that call printf (or any other print function) at relevant places in our code and output values of variables or just print a message that indicates that the execution of the program has reached this particular line in the code. Then we recompile the program, run it, reproduce the problem, and add more printf calls until we find the bug.

There is nothing wrong with printf debugging. It is the most basic method of debugging and it works quite well in many situations and is available to the programmer in nearly any environment. Lots of programs even write a log file during normal operation to help track down problems that happened in production. Log files are nothing else than built-in, glorified printf debugging.

printf debugging is great but it has its limitations. For example, you can’t step through a program line by line or just jump into a specific location and look around exploring the variables and the state of the program at the time.

Whenever you want to check a new variable or data structure that wasn’t on your radar before you have to add new printf statements to the code, recompile it, run it, and get the program into the desired error state. Also, there is no way to halt the program every time a certain variable or memory address is read or modified and see from which line of code the memory access happened.

All these things and more can be done with a debugger. And that is why it is crucial to know a good debugger and know it well.

One of the most popular and powerful debuggers is gdb. And it is also available on more platforms than probably any other debugger. This article will show you everything you need to know to debug your own programs with gdb.

Fixing a simple Crash

Let’s say you write a program in C or C++ and it crashes. While in languages like Java or Python, you will get a full-fledged stack trace all you get in our case is the message “Segmentation fault” in the terminal from which you started your program.

Continue reading “Getting started with GDB”

Structures in C: From Basics to Memory Alignment

Structures allow us to combine several variables to create a new data type. Some other languages support the same concept but call it “records”. If you come from object-oriented programming you can think about them as classes without methods.

Declaration

A structure is declared by the keyword struct followed by the name of the new structure and a list of its members enclosed in parentheses:

struct s {
    char a;
    int b;
    double c;
    char d[10];
};

Here we declared a new structure with the name s that has the members a (a single character), b (an integer), c (a double), and d (a char array of size 10 which can store up to 9 characters and a terminating null character).

Continue reading “Structures in C: From Basics to Memory Alignment”

Simple Raspberry Pi Backup

So you have set up your Raspberry Pi as a home server and everything works as intended. But what if the SD card fails and all the data you stored on your Raspberry Pi is suddenly lost forever?

All storage devices containing important data need to be backed up on a regular basis. And this is even more true for SD cards than for most other storage media. Because unlike hard drives and SSDs, SD cards are not really made for installing operating systems on them and they are also not designed for being powered on 24/7. Therefore, SD cards have a comparatively high risk of failing.

One thing is for sure: Your new Raspberry Pi needs a backup solution!

Wouldn’t it be nice if you just had a little Python script on your Linux PC that whenever executed logged on the Raspberry Pi via SSH, fetched all your data, and put it into a new timestamped subdirectory?

This is actually much easier than you might think. So let’s dive into this problem!

Continue reading “Simple Raspberry Pi Backup”

The Anomaly of the char Type in C

When we declare a variable of type int and we don’t tell the compiler if it is supposed to be signed or unsigned it is signed by default:

signed int s_number;   // signed
unsigned int u_number; // unsigned
int number; // equivalent with signed int

This is true for all integer number types (short, int, long, long long).

But there is one exception: The char type!

The char Type is Special

According to the C Standard, it depends on the implementation if char is signed or unsigned. The standard also says that char doesn’t collapse into one of signed char or unsigned char but is considered its own type (although it is represented internally as signed or unsigned, of course).

But the most surprising thing to know about char is that it is not guaranteed to be 8 bits. That means the C Standard does not guarantee a byte to be 8 bits. There are some very old architectures where char is 9 bits wide for example.

Fortunately for us, basically all architectures in use today have bytes that are 8 bits wide. Still, a program that assumes char to be 8 bits wide will not be portable to every platform where a C compiler is available.

Ask the Compiler

The characteristics of the char type (as well as all other types) are exposed in the standard header file limits.h. Therefore we can write a simple C program to find out how char is implemented on our platform:

#include <stdio.h>
#include <limits.h>

int main(void)
{
    printf("char bits:         %d\n", CHAR_BIT);
    printf("char is:           %s\n", CHAR_MIN < 0 ? "signed" : "unsigned");
    printf("signed char min:   %d\n", SCHAR_MIN);
    printf("signed char max:   %d\n", SCHAR_MAX);
    printf("unsigned char min: 0\n");
    printf("unsigned char max: %d\n", UCHAR_MAX);

    return 0;
}
Continue reading “The Anomaly of the char Type in C”

How to Update Your Website with rsync

Did you ever upload a website via FTP, scp, or even a clunky web uploader?

This can be quite cumbersome. Especially, when you forget to upload certain files and as a result, your website is broken. And doing this over and over again and trying very hard to make no mistakes can really break your spirit.

There must be a better way.

And there is! You can just sync the local directory where you keep the code of your website with rsync. This amazing tool will check each file and each subdirectory and make sure that the files that are on your server are in sync with the files on your computer. It can also delete all files that exist on the server but not on your local machine.

my-website/
├── css/
|   ├── mobile.css
│   └── style.css
├── downloads/
|   ├── download.zip
│   └── ...
├── fonts/
│   └── ...
├── js/
|   ├── jquery.js
│   └── ...
├── images/
│   └── ...
├── index.php
├── about.php
├── ...
└── sync.sh

Let’s say we have a classic PHP website. You can then just add a sync.sh script at the root of your project directory:

Continue reading “How to Update Your Website with rsync”

Better than Singletons: The Service Locator Pattern

One of the biggest problems in object-oriented programming is getting access to the objects you need.

A very common solution to this problem is dependency injection. This means you have to pass every method the objects it needs to do its work (you can also pass them to the constructor of the methods object and store them in member variables). What sounds easy and logical at first also gets messy quite quickly when applied in practice.

With dependency injection, you have to make sure the right objects are available where ever they are needed. That means you often have to pass several objects to the same method and you have to add new parameters to methods and constructors all the time. As your code grows bigger passing those objects through your project starts to feel very repetitive and when you refactor your code you have to touch a lot more methods than you would need to touch without dependency injection.

Continue reading “Better than Singletons: The Service Locator Pattern”

How to Create a Modern C Project with CMake and Conan

The C programming language is over 50 years old. Despite its age, it is still going strong. Many languages have tried to replace it. But so far none did succeed. To this very day, C is still the foundation on which all the software we use each and every day ultimately depends.

But with such a long history it comes as no surprise that there are a lot of legacy C projects out there. Projects that use outdated build systems and outdated practices. This is really a shame because, in this day and age, we have many awesome new tools at our fingertips that can help us tremendously when it comes to writing better and more robust C code.

So what if we would start a new C project from scratch today? How would we structure it? How would we build it? And what tools and features would we integrate into the build system from the start?

There are many possible answers to this question but in this article, I want to give you mine. And that’s why we are going to build the template of a modern C project from scratch. There will be code and it will compile into an executable but our main focus will be on the build system.

Continue reading “How to Create a Modern C Project with CMake and Conan”