72

Basically, I want to get typeid(*this).name(), i.e. the real type of this.

I want to get this in GDB (without modifying the source code). I tried print typeid(*this) but it says that typeid is unknown (because I didn't included it there in the source file).

Albert
  • 65,406
  • 61
  • 242
  • 386

4 Answers4

80

Use ptype command, like this:

(gdb) ptype 42
type = int
Star Brilliant
  • 2,916
  • 24
  • 32
  • This returns things like `type = unsigned short`, but I want it to return `type = uint16_t` instead, so I can truly know how many bytes it is when inspecting memory. Is there any way to do that? The best I can figure out is to do `print &my_var`, which prints `(uint16_t *) 0x7ffffffefc2c`, thereby revealing that its pointer type is `uint16_t*`, meaning its type is `uint16_t`. – Gabriel Staples Aug 13 '20 at 22:39
  • I presented this as an answer, but if you have a better way to do this I'm all ears: https://stackoverflow.com/a/63404160/4561887. – Gabriel Staples Aug 14 '20 at 00:24
22

Use ptype, whatis, and explore (my favorite!):

Where you have a variable named value which is defined as:

uint32_t value = 1234;

...the following all work:

  1. ptype value shows unsigned int
  2. whatis value shows uint32_t
  3. explore value (my favorite!) shows:
    The value of 'value' is of type 'uint32_t' which is a typedef of type 'unsigned int'
    'value' is a scalar value of type 'unsigned int'.
    value = 1234
    

Example:

(gdb) ptype value
type = unsigned int
(gdb) ptype &value
type = unsigned int *
(gdb) whatis value
type = uint32_t
(gdb) explore value
The value of 'value' is of type 'uint32_t' which is a typedef of type 'unsigned int'
'value' is a scalar value of type 'unsigned int'.
value = 1234

Thanks to @o11c's comment below for pointing out the existence of the whatis command.

I discovered the explore command by running help all inside gdb. See my comment in the "References" section below.

Try it yourself:

# download the file "type_punning.c"
wget https://raw.githubusercontent.com/Generalsimus/eRCaGuy_hello_world/master/c/type_punning.c

# build it with optimization OFF (`-O0`) and debugging symbols ON (`-ggdb`), 
# and output all intermediary files (`-save-temps=obj`), and run it in the 
# gdb debugger (`gdb bin/type_punning`)
mkdir -p bin && gcc -Wall -Wextra -Werror -O0 -ggdb -std=c11 -save-temps=obj \
type_punning.c -o bin/type_punning && gdb bin/type_punning

Now, with gdb running, do the following:

# set breakpoint to a line just after `u.value = 1234;`
b type_punning.c:52
# run to that point
r
# Now run these various commands to see what type `u.value` is:
ptype u.value
whatis u.value 
explore u.value  

Full example commands and output:

eRCaGuy_hello_world/c$ mkdir -p bin && gcc -Wall -Wextra -Werror -O0 -ggdb -std=c11 -save-temps=obj type_punning.c -o bin/type_punning && gdb bin/type_punning
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from bin/type_punning...done.
(gdb) b type_punning.c:52
Breakpoint 1 at 0x70b: file type_punning.c, line 52.
(gdb) r
Starting program: /home/gabriel/GS/dev/eRCaGuy_hello_world/c/bin/type_punning 
Type punning and ptr-based serialization demo
TECHNIQUE 1: union-based type punning:

Breakpoint 1, main () at type_punning.c:53
53          printf("1st byte = 0x%02X\n", (u.bytes)[0]);
(gdb) ptype u.value
type = unsigned int
(gdb) whatis u.value 
type = uint32_t
(gdb) explore u.value  
The value of 'u.value' is of type 'uint32_t' which is a typedef of type 'unsigned int'
'u.value' is a scalar value of type 'unsigned int'.
u.value = 1234
(gdb) 

My old/original answer

As @Star Brilliant says here, this:

ptype my_var

returns things like type = unsigned short, but I want it to return type = uint16_t instead, so I can truly know how many bytes it is when inspecting memory. The best I can figure out to get this effect is to do:

print &my_var

which prints (uint16_t *) 0x7ffffffefc2c, thereby revealing that its pointer type is uint16_t*, meaning its type is uint16_t.

I find this to be more-useful than ptype my_var, but a more direct way to get this effect is desired in case you have any suggestions.

Sample gdb commands and output:

(gdb) ptype my_var
type = unsigned short
(gdb) print &my_var
$27 = (uint16_t *) 0x7ffffffefc2c

Again, notice ptype my_var reveals it is an unsigned short, whereas print &my_var reveals the more-detailed and desired answer which is that it is a uint16_t.

References:

  1. @o11c's comment below
  2. @Star Brilliant's answer
  3. help all - I used this command while running gdb, copy-pasted the output all to a text editor, and searched for "type" to discover the explore command.

See also:

  1. My answer on How to view a pointer like an array in GDB?
  2. My answer on How to use printf in GDB in order to write a custom description around your variable output
  3. [my ans.] "gdb" debugger skips a break point weirdly
  4. [my Q&A] What's the difference between a compiler's `-O0` option and `-Og` option?
  5. [my Q&A] https://askubuntu.com/questions/1349047/where-do-i-find-core-dump-files-and-how-do-i-view-and-analyze-the-backtrace-st

Keywords: how to run gdb; how to view variable types and values in gdb; how to build and compile for gdb debugging symbols

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
  • 1
    `whatis` is a thing. – o11c Oct 12 '21 at 18:05
  • @o11c, thanks! It turns out `explore` is a really nice command too. I've just massively updated my answer. – Gabriel Staples Oct 12 '21 at 22:02
  • while in TUI mode (split screen with source code; `tui enable`), when I executed `explore somevariable`, the *gdb* prompt showed "*... Continue exploring it as a pointer to a single value [y/n]:*". But I couldn't enter any answer (*y* or *n*). It seems the TUI mode swallowed my answer input. I first had to cancel the `explore somevariable` command by pressing `Ctrl+c Ctrl+d`, then disable TUI mode with `tui disable`. Repeating `explore somevariable` now allowed me to answer the question. – Abdull Aug 17 '23 at 09:26
  • @Abdull, I think you just need to press `Ctrl` + `X`, then `o`, to switch focus back from the TUI window to the 'o'ther window where the GDB commands go. I have that command saved [in my notes here](https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/git%20%26%20Linux%20cmds%2C%20help%2C%20tips%20%26%20tricks%20-%20Gabriel.txt#L1703). Search the doc for `Ctrl + X, o`. – Gabriel Staples Aug 17 '23 at 19:06
18

The ptype [ARG] command will print the type.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
t. fochtman
  • 431
  • 3
  • 9
  • 4
    At least in gdb v7.6.1 that doesn't help with this question, as it only prints the static type, not the polymorphic type. For example where "d" is an object of type "D" derived from base class "B" then `B* b = &d; (gdb) ptype b type = class B {` – Tom Goodfellow May 27 '14 at 15:10
  • 1
    [with "set print object on" it gets prefixed with `type = /* real type = D * */` but then so does "whatis"] – Tom Goodfellow May 27 '14 at 15:16
13

This question may be related: vtable in polymorphic class of C++ using gdb:

(gdb) help set print object
Set printing of object's derived type based on vtable info. 

It's not exactly typeid() but it should show the real object type when inspecting a polymorphic pointer (e.g. this in a base class). Naturally works only for classes with a vtable (i.e. at least one virtual method) but so does typeid.

Community
  • 1
  • 1
regnarg
  • 676
  • 8
  • 10