Reputation: 814
I post this after a quick search on stackoverflow...
I got trouble to print a VLA entry from GDB, here is my streamlined C fragment.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{ int i, j;
} c_t;
int f(int l, int c, c_t a[l][c])
{ for(int i=0;i<l;i++)
{ for(int j=0;j<c;j++)
{ a[i][j].i=i; a[i][j].j=j;
}
}
}
int main(int ac, char **av)
{ int l=(int)atoi(av[1]), c=(int)atoi(av[2]);
c_t a[l][c];
return(f(l,c,a));
}
I compile it
$ cc -o g g.c -g -O0
Then run GDB on it, and after a couple of iteration in f() I try to display a[i][j]
$ gdb ./g
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
...[snip]...
Reading symbols from ./g...done.
(gdb) r 2 3
Breakpoint 1 at 0x76b: file g.c, line 17.
Breakpoint 1, main (ac=3, av=0x7fffffffe608) at g.c:17
17 { int l=(int)atoi(av[1]), c=(int)atoi(av[2]);
(gdb) n
18 c_t a[l][c];
(gdb)
19 return(f(l,c,a));
(gdb) s
f (l=2, c=3, a=0x7fffffffe440) at g.c:8
8 int f(int l, int c, c_t a[l][c])
(gdb) n
9 { for(int i=0;i<l;i++)
(gdb)
10 { for(int j=0;j<c;j++)
(gdb)
11 { a[i][j].i=i; a[i][j].j=j;
(gdb)
10 { for(int j=0;j<c;j++)
(gdb)
11 { a[i][j].i=i; a[i][j].j=j;
(gdb)
10 { for(int j=0;j<c;j++)
(gdb)
11 { a[i][j].i=i; a[i][j].j=j;
(gdb)
10 { for(int j=0;j<c;j++)
(gdb)
9 { for(int i=0;i<l;i++)
(gdb) p a[0][0]
Cannot perform pointer math on incomplete types, try casting to a known type, or void *.
(gdb)
From there I am stuck, tried various cast with no success.
Thanx in advance for any pointers (may be pointers are better than arrays :) )
Phi
Upvotes: 2
Views: 360
Reputation: 70472
When you print a
from the debugger, you should get a big hint:
...
Breakpoint 1, f (l=2, c=3, a=0x7fffffffe1b0) at x.c:8
8 int f(int l, int c, c_t a[l][c])
(gdb) p a
$1 = (c_t (*)[variable]) 0x7fffffffe1b0
The debugger understands that a
is a pointer to a VLA of c_t
, but feigns ignorance on the actual length of that array. However, you know that it is 3
(the value of c
). So you can simply cast it as such.
(gdb) p c
$2 = 3
(gdb) p (c_t (*)[3])a
$3 = (c_t (*)[3]) 0x7fffffffe1b0
(gdb) p $3[0][0]
$4 = {i = -7552, j = 32767}
Upvotes: 3
Reputation: 133978
You can check the dimensions from the variables and make a pointer to an array of defined size. It is not optimal, of course. But that way you can even see the entire array:
(gdb) p ((c_t (*)[3])a)[0][1]
$30 = {i = 0, j = 1}
(gdb) p ((c_t (*)[3])a)[1][1]
$31 = {i = 1, j = 1}
(gdb) p *((c_t (*)[2][3])a)
$29 = {{{i = 0, j = 0}, {i = 0, j = 1}, {i = 0, j = 2}}, {{i = 1, j = 0}
{i = 1, j = 1}, {i = 1, j = 2}}}
Upvotes: 2
Reputation: 27126
What's supposed to work always, it's actually pointer arithmetic.
You can use something like the following commands:
(gdb) p *((c_t*)a+0*3+0)
$3 = {i = 0, j = 0}
(gdb) p *((c_t*)a+0*3+1)
$4 = {i = 0, j = 1}
(gdb) p *((c_t*)a+0*3+2)
$5 = {i = 0, j = 2}
(gdb) p *((c_t*)a+1*3+0)
$6 = {i = 1, j = 0}
(gdb) p *((c_t*)a+1*3+1)
$7 = {i = 1, j = 1}
(gdb) p *((c_t*)a+1*3+2)
$8 = {i = 1, j = 2}
BTW: not related to your question: The function signature for f
specifies a return value of type int
, but does not return anything.
Upvotes: 2