cdebuggingvisual-studio-codevscode-debugger

How to watch char values of strings pointed by a pointer to pointers in debugger mode of VSCode


Let's say I'm working with this C program.

#include <string.h>
#include <stdlib.h>

int     main(void)
{
    char    *p0 = strdup("red..");
    char    *p1 = strdup("green");
    char    *p2 = strdup("blue.");
    char    *p3 = NULL;
    char    **pp = malloc(sizeof(char *) * 4); /* I want to watch this in VSCode debugger */

    pp[0] = p0;
    pp[1] = p1;
    pp[2] = p2;
    pp[3] = p3;

  /* do something */

    return (0);
}

What I want to achieve

In the watch view of VSCode debugger, how do I get it to display the char values (and addresses if possible) of the strings pointed by each pointers like the following?

<watch_expression_for_pp>: <address of pp>
   |- pp[0]: [6] <address of pp[0]>
   |     |--- [0]: 'r'
   |     |--- [1]: 'e'
   |     |--- [2]: 'd'
   |     |--- [3]: '.'
   |     |--- [4]: '.'
   |     |--- [5]: '\0'
   |
   |- pp[1]: [6] <address of pp[1]>
   |     |--- [0]: 'g'
   |     |--- [1]: 'r'
   |     |--- [2]: 'e'
   |     |--- [3]: 'e'
   |     |--- [4]: 'n'
   |     |--- [5]: '\0'
   |
   |- pp[2]: [6] <address of pp[2]>
   |     |--- [0]: 'b'
   |     |--- [1]: 'l'
   |     |--- [2]: 'u'
   |     |--- [3]: 'e'
   |     |--- [4]: '.'
   |     |--- [5]: '\0'
   |
   |- pp[3]: [6] <0x0000000000000000>
         |--- [0]: 'r'
         |--- [1]: 'a'
         |--- [2]: 'n'
         |--- [3]: 'd'
         |--- [4]: 'o'
         |--- [5]: 'm'

What I already know

I know that if I add (char(*)[6])pp[0] as an watch expression, I will be able to view the 6 char values from pp[0][0] to pp[0][5], but that's not an ideal solution if I'm dealing with hundreds of pointers and need to go through the values quickly.

watch char values of a single string

I'm looking for a way to add one watch expression, and be able to get a view like above, just like when I'm watching a linked list in the debugger.
Or, a completely different approach, like using an extension.


Solution

  • This should do the job (but also see below for a cleaner solution):

    (char (*(*)[4])[6])pp
    

    enter image description here

    As you can see, you were already really close!

    Of course, the strings you use may not have a fixed size so the second dimension [6] would not be accurate and should probably match the longest string that you expect. Hence for shorter strings, you might see some gibberish from the adjacent memory locations.

    Edit: As I later figured out, you can also drop the second dimension and use this much cleaner version:

    (char (*(*)[N]))pp
    

    where N is the number of strings you have in your array.