Debug C++ Applications With Docker
September 22, 2020

How to Debug C++ Applications in a Docker Container

High Performance Computing

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 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.

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.

Debug in a Docker Container With TotalView

Requirements

This example uses Docker 19.03, Ubuntu 19, and TotalView 2020.2.

Don't have TotalView? Request an evaluation version here. >> 

Steps

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

  • Dockerfile
  • test.cxx
  • totalview_2020.2.6_linux_x86-64.tar
  • license.demo (skip this if you are using a TotalView license server)

2. Create a Dockerfile.
 

# Use Docker gcc 
FROM gcc:latest

# 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.cxx -o test

# Extract the totalview tar file
RUN tar xvf totalview_2020.2.6_linux_x86-64.tar

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

# Copy the license key to the totalview license directory
RUN cp license.demo /usr/toolworks/flexlm-11.16.6-0/

# Run the TotalView GUI 
CMD ["/usr/toolworks/totalview.2020.2.6/bin/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/flexlm-11.16.6-0/ 


and replace it with:

ENV [email protected] 


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 Docker build command to create a Docker image called “tv-debug” from all the files in the current directory. Alternatively, you can specify the image name in a separate Docker yml file. 

docker build -t tv-debug


6. 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).

xhost +local:root


7. Run the Docker image as a container.

docker run -it \ 
--env="DISPLAY" \ 
--env="QT_X11_NO_MITSHM=1" \ 
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
tv-debug


Here we make the container's processes interactive, forward our DISPLAY environment variable and mount a volume for the X11 unix socket.

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

Debug C++ TotalView GUI

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

Debug C++ TotalView GUI

10. 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 this video tutorial of reverse debugging,

11. You can also set a watchpoint on the array length variable after moving it to the Data View to observe when its value is changed. 

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

xhost -local:root


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