Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-12

GDB - cannot perform pointer math on incomplete types

9 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

David Emerson

This error message has often befuddled me when debugging. I've got a dynamic array, usually a type that I've created, e.g. type longint_arr = array of longint
I'm using the Watch List and want to inspect one of the elements of such an array, e.g. f_list[0]. But I get this error, which I guess comes from GDB. Is there any way I can coerce it into giving me f_list[0], or even f_list[1]?

Thanks,
David

Reply by email

Martin
to David Emerson
David Emerson wrote 8 lines
This error message has often befuddled me when debugging. I've got a dynamic array, usually a type that I've created, e.g. type longint_arr = array of longint I'm using the Watch List and want to inspect one of the elements of such an array, e.g. f_list[0]. But I get this error, which I guess comes from GDB. Is there any way I can coerce it into giving me f_list[0], or even f_list[1]?

I would need a complete example....
Also Laz/fpc version...

Sometimes this message appears, if you declare an array without a type name. So instead of

   type TMyArray = array of integer; var Foo: TMyArray;

you do:

   var Foo: array of integer;

If the type of the element is named, then do
^integer(Foo)[1]
Nested Array
^^integer(Foo)[1][2]

If it is a static array "array[3..5]" then the pointer type cast still starts at index 0 (so you must subtract the low bound from all indices)

It may also happen with nested arrays, and (unnamed (inline in "var" declared) records)

   var Foo: array of record ... end;

You may also try switching between stabs and dwarf (project options / /linking)

Reply by email

Martin
to Martin
Martin wrote 14 lines
On 04/12/2012 01:54, David Emerson wrote: > This error message has often befuddled me when debugging. > I've got a dynamic array, usually a type that I've created, e.g. > type longint_arr = array of longint > I'm using the Watch List and want to inspect one of the elements of > such an > array, e.g. f_list[0]. But I get this error, which I guess comes from > GDB. > Is there any way I can coerce it into giving me f_list[0], or even > f_list[1]? > I would need a complete example.... Also Laz/fpc version...

Or supply a log:
http://wiki.lazarus.freepascal.org/GDB_Debugger_Tips#Log_info_for_debug_session

Reply by email

David Emerson

-------- Original Message --------

Show quoted text 7 lines
From: "Martin" On 04/12/2012 01:54, David Emerson wrote: > This error message has often befuddled me when debugging. > I've got a dynamic array, usually a type that I've created, e.g. > type longint_arr = array of longint > I'm using the Watch List and want to inspect one of the elements of

such an

> array, e.g. f_list[0]. But I get this error, which I guess comes from

GDB.

Show quoted text 8 lines
> Is there any way I can coerce it into giving me f_list[0], or even > f_list[1]? > I would need a complete example.... Also Laz/fpc version... Sometimes this message appears, if you declare an array without a type

name.

Show quoted text 20 lines
So instead of type TMyArray = array of integer; var Foo: TMyArray; you do: var Foo: array of integer; If the type of the element is named, then do ^integer(Foo)[1] Nested Array ^^integer(Foo)[1][2] If it is a static array "array[3..5]" then the pointer type cast still starts at index 0 (so you must subtract the low bound from all indices) It may also happen with nested arrays, and (unnamed (inline in "var" declared) records) var Foo: array of record ... end; You may also try switching between stabs and dwarf (project options / /linking)

Thanks much!! The first suggestion ^integer(foo)[1] works great!

Reply by email

Martin
to David Emerson
David Emerson wrote
Thanks much!! The first suggestion ^integer(foo)[1] works great!

Still if you can get me the log + unit source ?

because the IDE in many cases tries to work those out. So I wonder what happens behind the curtains...

Reply by email

David Emerson
Martin wrote 5 lines
Still if you can get me the log + unit source ? because the IDE in many cases tries to work those out. So I wonder what happens behind the curtains...

Hmm I am working on it ... can't really share the sources :( but I am trying to build a miniature version to reproduce it. In the meantime:

The watch item I created looks like this:
tsrl_ag_cp(f_ag).f_curve.f_cps.f_list[0]
and after your suggestion, was fixed like this:
^pointer(tsrl_ag_cp(f_ag).f_curve.f_cps.f_list)[0]

SELF is a class with field f_ag : tsrl_ag
tsrl_ag_cp descends from tsrl_ag
tsrl_ag_cp has field f_curve : tsrl_curve
tsrl_curve has field f_cps : tsrl_ag_cp_list
tsrl_ag_cp_list descends from t_ordered_ag_list
t_ordered_ag_list = specialize gt_unsorted_pointer_list <tsrl_ag> generic gt_unsorted_pointer_list <_class> = class
(t_unsorted_pointer_list)
t_unsorted_pointer_list is a class with field f_list : ptr_array and type ptr_array = array of pointer

So as you can see it is a little complicated :-)

Reply by email

Martin
to David Emerson
David Emerson wrote 25 lines
Martin wrote: > Still if you can get me the log + unit source ? > > because the IDE in many cases tries to work those out. So I wonder what > happens behind the curtains... Hmm I am working on it ... can't really share the sources :( but I am trying to build a miniature version to reproduce it. In the meantime: The watch item I created looks like this: tsrl_ag_cp(f_ag).f_curve.f_cps.f_list[0] and after your suggestion, was fixed like this: ^pointer(tsrl_ag_cp(f_ag).f_curve.f_cps.f_list)[0] SELF is a class with field f_ag : tsrl_ag tsrl_ag_cp descends from tsrl_ag tsrl_ag_cp has field f_curve : tsrl_curve tsrl_curve has field f_cps : tsrl_ag_cp_list tsrl_ag_cp_list descends from t_ordered_ag_list t_ordered_ag_list = specialize gt_unsorted_pointer_list <tsrl_ag> generic gt_unsorted_pointer_list <_class> = class (t_unsorted_pointer_list) t_unsorted_pointer_list is a class with field f_list : ptr_array and type ptr_array = array of pointer So as you can see it is a little complicated :-)

Ok there are 2 possible bits in there.

1) maybe fpc does some odd debug info with generics. Never tested. Unknown

2) The type cast to the class. GDB can get the hick ups, because classes are pointers, and gdb half-knows it....

try
    ^tsrl_ag_cp(f_ag).f_curve.f_cps.f_list[0]

Reply by email

David Emerson
Still if you can get me the log + unit source ? because the IDE in many cases tries to work those out. So I wonder what happens behind the curtains...

I just constructed this program, which allows me to reproduce the issue. I put a breakpoint on the writeln.
Watch List items:
tsrl_ag_cp(cf.f_ag).f_curve.f_cps.f_list[0] -- gives GDB error ^tsrl_ag_cp(tsrl_ag_cp(cf.f_ag).f_curve.f_cps.f_list)[0] -- succeeds

I'll see how much of this I can cut out and still reproduce :)

program dumdum;
{$mode objfpc}
uses classes;
type
  ptr_array = array of pointer;
  tsrl_ag = class (tobject);
  t_list_frame = class (tobject)
    f_list : ptr_array;
    end;
  t_unsorted_pointer_list = class (t_list_frame)
    procedure add (p : pointer);
    end;

generic gt_unsorted_pointer_list <_class> = class
(t_unsorted_pointer_list)

    end;
  t_ordered_ag_list = specialize gt_unsorted_pointer_list <tsrl_ag>;
  tsrl_ag_cp_list = class (t_ordered_ag_list);
  tsrl_shape = class
    f_ag : tsrl_ag;
    end;
  tsrl_crowsfoot_icon = tsrl_shape;
  tsrl_curve = class (tsrl_shape)
    f_cps : tsrl_ag_cp_list;
    end;
  tsrl_ag_cp = class (tsrl_ag)
    f_curve : tsrl_curve;
    end;
procedure t_unsorted_pointer_list.add (p : pointer);
  var l : longint;
  begin
    l := length(f_list);
    setlength (f_list, l+1);
    f_list[l] := p;
  end;
var
  cf : tsrl_crowsfoot_icon;
  cf_ag, other_cp : tsrl_ag_cp;
  curve : tsrl_curve;
begin
  cf_ag := tsrl_ag_cp.create;
  other_cp := tsrl_ag_cp.create;
  curve := tsrl_curve.create;
  curve.f_cps := tsrl_ag_cp_list.create;
  curve.f_cps.add(other_cp);
  curve.f_cps.add(cf_ag);
  cf_ag.f_curve := curve;
  cf := tsrl_crowsfoot_icon.create;
  cf.f_ag := cf_ag;
  writeln ('hi');
end.

Reply by email

Martin
to David Emerson
David Emerson wrote 12 lines
> Still if you can get me the log + unit source ? > > because the IDE in many cases tries to work those out. So I wonder what > happens behind the curtains... I just constructed this program, which allows me to reproduce the issue. I put a breakpoint on the writeln. Watch List items: tsrl_ag_cp(cf.f_ag).f_curve.f_cps.f_list[0] -- gives GDB error ^tsrl_ag_cp(tsrl_ag_cp(cf.f_ag).f_curve.f_cps.f_list)[0] -- succeeds I'll see how much of this I can cut out and still reproduce :)

Thanks, this is ok. I can reproduce.
I do not need it any simpler.

Btw with dwarf, both work, but the first returns the address only

Reply by email