About Blog Contact

GDB: Printing Variables to File

GDB is a great tool for debugging C and C++ code. To inspect the value of a variable, one can simply use the print command. However, when the variable is an array, and it’s too large to print, or when you need to examine it carefully with other tools, then you may want to save it to a local file for further examination. Here is my guide for doing just that.

Setting the Logging and Printing Options

First, a quick guide. Just run the following commands:

set max-value-size unlimited
set print elements 0 
set print repeats 0
set pagination off
set logging file file_to_save_data
set logging on

Then, the output of the next print command would be redirected to file_to_save_data. Explanation for each command:

There are also many more settings that you could make, most of which are in the print section. Look it up if the output is not good enough.

How to Output Arrays

Imagine you have a pointer to array int* arr = new int [10];. If you run print arr, then GDB would output:

(int *) 0x55555556aeb0

its type and its address (virtual of course). To output it’s zeroth member, run print arr[0], just like you would in code. To print it in its entirety, you need to to specify the number of elements to print, as GDB would have no way of knowing it. Run:

print *arr@10

To print the first ten elements of the array. You can do pointer arithmetic on the arr pointer, for example, to print the second element and third:

print *(arr+1)@2

You can also use a more convoluted way to do it:

print *(int(*) [10])arr

First it casts the pointer-to-int to pointer-to-array-of-int, then dereferences it. Of course, I think the above method is better. See this post for more options.

Outputting Device Data in cuda-gdb

cuda-gdb is an extension to GDB developed by Nvidia, for debugging CUDA code on actual hardware. It’s based on GDB, so most of GDB’s commands are supported. To print a pointer to variables in device memory, either global or shared, you need to add a little bit. To print the first 18 members of shared double* ptr which points to somewhere in shared device memory, use:

print ptr[0]@18

Sometimes the variable is not declared with the __shared__ or __device__ directive (to interface with non-cuda code, for example), so you’d need to explicitly cast it:

print ((@shared double *)ptr)[0]@18

Global memory can be also printed in a similar way. All the logging to file and redirection works exactly the same as with GDB.