Debug C++ Applications With Docker
July 10, 2024

How to Debug C++ Applications in a Docker Container

Technologies & Languages

Application development, debugging, and testing are increasingly being done in a containerized environment due to the many advantages this approach offers such as efficient use of system resources, faster software delivery cycles, application portability, and microservices architecture.

This short and easy-to-follow blog will show how to compile a simple C++ application for debugging, and to debug that application with the TotalView graphical debugger, inside a Docker container.

Back to top

What is Docker?

Docker is a set of platform as a service (PaaS) products that use OS-level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their own software, libraries and configuration files; they can communicate with each other through well-defined channels. All containers are run by a single operating system kernel and therefore use fewer resources than virtual machines.

Back to top

Debug in a Docker Container With TotalView

Requirements

This example uses Docker 26.1.4, Ubuntu 20.04, gcc 10.2 and TotalView 2024.1. You can request a TotalView evaluation from the TotalView website.

Don't have TotalView?Start your free trial. 

Steps

1. Create a directory called TotalView where we will place the following files:

  • Dockerfile
  • run.bat
  • test.cxx
  • totalview_2024.1.21_linux_x86-64.tar
  • license.demo (skip this step if you are using a TotalView license server)

2. Start a Dockerfile.
 


# Use Docker gcc 
FROM gcc:10.2

# Install required libraries for TotalView
RUN apt-get update && apt-get install -y \
    libgl1-mesa-glx \
    libnss3 \
    libxcomposite-dev \
    libxcursor1 \
    libxi6 \
    libxtst6 \
    libdbus-1-dev \
    libxcb-cursor0 \
    libqt5x11extras5

# Copy the current folder which contains C++ source code to the Docker image under /home/username
COPY . /home/stewart

# Specify the working directory
WORKDIR /home/stewart

# Use GCC to compile the Test.cpp source file with debug symbols
RUN g++ -g test.cpp -o test

# Extract the totalview tar file
RUN tar xvf totalview_2024.1.21_linux_x86-64.tar

# Change to the totalview directory and run totalview installation
RUN cd totalview.2024.1.21 && ./Install -agree -default

# Copy the license key to the totalview license directory
RUN cp license.demo /usr/toolworks/tv_license/

# open port 22
EXPOSE 22

# add TotalView bin directory to PATH
ENV PATH="${PATH}:/usr/toolworks/totalview.2024.1.21/bin"

# Run the TotalView GUI 
#CMD ["totalview"]


3. Place the license.demo temporary license file in the TotalView directory.

If you are using an existing TotalView license server you can ignore this step and instead modify the Dockerfile to remove the line copying the demo license key:

# RUN cp license.demo /usr/toolworks/tv_license 


and replace it with:

ENV LM_LICENSE_FILE=port@server 


with the Dockerfile to point to your existing TotalView license server.

4. Create a test.cpp file.

/* Test example */
/* Produces a seg fault */


#include <iostream>


int funcA(int);
int funcB(int);
int badstuff();
#define MAXDEPTH 20
int arraylength=MAXDEPTH;


int main()
{
    funcA(0);
    badstuff();
    funcA(0);
    exit(1);
}



int funcA(int a){
    int b;
    b=a+2;
    b=funcB(b);
    return b;
}


int funcB(int b){
    int c;
    int i;
    int v[MAXDEPTH];
    int *p;

    c=b+2;
    p=&c;

    if( c<MAXDEPTH )  
       c=funcA(c);

    for (i=arraylength-1; i>0; i--){
        v[i]=*p;
    }

    return c; 
}

int badstuff(){
    arraylength=5*MAXDEPTH;
    return 0;
}


5. Run the run.bat batch script

a. Adjust the permissions on the X-server host to temporarily allow the root user to use the local user’s X session (note: this has security implications so we will reset it after finishing the debugging session).

b. Build the Docker image.

c. Run the Docker image as a container.

# Adjust permissions on X-Server host to temporarily allow root to use local users X session
xhost +local:root

# Build the Docker image 
docker build -t totalview .

# Run the Docker image
docker run -it \
--env="DISPLAY" \
--env="QT_X11_NO_MITSHM=1" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
totalview /bin/bash


6. Start TotalView and select Debug a Program from the TotalView GUI 

program session


7. Set a breakpoint at line 18 and Press GO to run to it. 

breakpoint at line 18

 

8. Step through reverse debugging. 

If you enabled Reverse Debugging you can now step forwards and backward through the code to try to isolate the cause of the segmentation fault. You can view a video tutorial of reverse debugging here.

9. Set a watchpoint. 

You can also set a watchpoint on the arraylength variable after moving it to the Data View to observe when its value is changed. You can view a video tutorial on using watchpoints here.

10. Reset Permissions

When you have finished the debugging session, reset the permissions on the X-server host.

xhost -local:root

❓ Need more help? Check out more TotalView resources. 
 

Back to top

Next Steps

This step by step guide showed you how to compile a simple C++ application for debugging, and to debug that application with the TotalView graphical debugger, inside a Docker container. 

Test TotalView's debugging capabilities with your application today.

Free trial

Back to top