Recent

Author Topic: Code critique required - saving TObjects as strings via Pointer  (Read 7262 times)

vfclists

  • Hero Member
  • *****
  • Posts: 1147
    • HowTos Considered Harmful?
I am trying to work out the relation between TObjects, pointers and saving pointers in string or hex format.
The second section in the code below the code works sometimes and SIGSEVs at other  times it works. What is the reason for this?

I am also interested if it can work on 64bit system without changes.

Code: [Select]
procedure TDesignerFormOne.btnGetComponentsClick(Sender: TObject);
var
  desForm: TDesignerFormOne;
  aPtr, bPtr: ^TObject;
  formAddr, APtrValue: string;
begin
  desForm := TDesignerFormOne.Create(self);
  //check thatthe address of any TObject is equivalant to pointer to TObject
  aPtr := @desForm;
  TForm(aPtr^).Caption := 'Pointer Works';

  //check that TObject equates to pointer, convert pointer to hex string;
  formAddr := IntToHex(PtrUInt(TObject(desForm)), 8);
  bPtr^ := TObject(UIntPtr(StrToInt('$' + formAddr)));
  TForm(bPtr^).Caption :=  TForm(bPtr^).Caption + ' - ' + 'cast of string to ptr worked';

  //display form to check
  desForm.Show();
  //desForm.Close();
end;
Lazarus 3.0/FPC 3.2.2

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4603
  • I like bugs.
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #1 on: June 18, 2013, 02:34:47 pm »
I am trying to work out the relation between TObjects, pointers and saving pointers in string or hex format.
The second section in the code below the code works sometimes and SIGSEVs at other  times it works. What is the reason for this?

You have made such a horrible hack that I am happy it crashes. Otherwise it might end up to your application and then crash later when something else changes.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11463
  • Debugger - SynEdit - and more
    • wiki
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #2 on: June 18, 2013, 02:47:20 pm »
Does StrToInt return something useful if the HIGHEST bit is set ?

Because $81234567 does not fit into an integer. The Hex string is a positive number, greater then maxint ($7fffffff). I doubt StrToInt makes that a negative number.


But I fully agree with Juha. This is a real bad hack. Whatever you try to do, this will keep giving you trouble. (as far as I can tell from my experience)

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #3 on: June 18, 2013, 02:47:35 pm »
@desForm    <>  PtrUInt(TObject(desForm))

Why just not keep in memory the TDesignerFormOne object reference , instead of using pointers ?

This one  is working (an horrible hack) , at least for a 32 bit version:

Code: [Select]
type ptrTObject =^TObject;
var
  desForm: TDesignerFormOne;
  aPtr, bPtr: ptrTObject;
  formAddr, APtrValue: string;
begin
  desForm := TDesignerFormOne.Create(self);
  //check thatthe address of any TObject is equivalant to pointer to TObject
  aPtr := @desForm;
  TForm(aPtr^).Caption := 'Pointer Works';

  //check that TObject equates to pointer, convert pointer to hex string;
  formAddr := IntToHex(PtrUInt(ptrTObject(@desForm)), 8);
  bPtr := ptrTObject(StrToInt('$' + formAddr));
  TForm(bPtr^).Caption :=  TForm(bPtr^).Caption + ' - ' + 'cast of string to ptr worked';

  //display form to check
  desForm.Show();
  //desForm.Close();end;



JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4603
  • I like bugs.
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #4 on: June 18, 2013, 03:26:33 pm »
@desForm    <>  PtrUInt(TObject(desForm))
Why just not keep in memory the TDesignerFormOne object reference , instead of using pointers ?
This one  is working (an horrible hack) , at least for a 32 bit version:

It would be more constructive to find a proper solution to vfclists's problem (whatever it is) instead of offering a little improvement to his horrible hack.
Please feel your responsibility guys.

The title says: "Code critique required". Apparently vfclists already knows his code deserves some critique. I don't know why he made it in the first place.
« Last Edit: June 18, 2013, 03:49:54 pm by JuhaManninen »
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #5 on: June 18, 2013, 04:56:34 pm »
@JuhaManninen:
Not quite sure about you mean, but it sounds definitively like a hard criticism.

About "@desForm    <>  PtrUInt(TObject(desForm))", it just means that a pointer to an object is not the object.

My former sample code deals with pointers. This one, not:
Code: [Select]
  formAddr := IntToHex(PtrUInt(TObject(desForm)), 8);
  bPtr := Pointer(UIntPtr(StrToInt('$' + formAddr)));
  TForm(bPtr).Caption :=  TForm(bPtr).Caption + ' - ' + 'cast of string to ptr worked';

Both of them are just trying to explain that you can't assimilate object pointer and object; full stop.
« Last Edit: June 18, 2013, 05:02:44 pm by ChrisF »

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4603
  • I like bugs.
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #6 on: June 18, 2013, 05:09:33 pm »
Not quite sure about you mean, but it sounds definitively like a hard criticism.
[...]
Both of them are just trying to explain that you can't mix pointer and object; full stop.

Ok, this last sentence is valid.
The original code just tries to make simple things more complicated, while good program code should do the opposite.
The problem vfclists has can surely be solved in a clean way without pointer syntax and hex string conversions.
« Last Edit: June 18, 2013, 06:42:06 pm by JuhaManninen »
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #7 on: June 18, 2013, 05:54:57 pm »
Apparently, the main vfclists's concern is to check that an object reference is in fact a pointer to this object data area: which may be or may be not  true.

Except that his first test (i.e. aPtr) is not about this concern: it just means that (@desForm)^=desForm. This one is supposed to be true for anything; just replace desForm by what_ever_you_like.

And except that his second test (i.e. bPtr) is incorrectly mixing references to an object and pointers to this object: which is also not the concern.

Anyway, even if this is correct (i.e. object reference = pointer to data object), it's certainly not a good idea to rely upon it; and absolutely not to deal with the data themselves.

And that's why keeping the reference of the object (i.e. desForm in his sample) is definitively more correct than to use any pointer to the object data themselves (i.e. "[...]Why just not keep in memory the TDesignerFormOne object reference[...]?"). Especially if this pointer may change internally. You are not supposed to "guess" about the internal object processes for the concerned language.

Plus, as desForm is in fact already a pointer (4 bytes for a 32 bit CPU) indeed, I can't see any good reasons to not using it.
« Last Edit: June 18, 2013, 06:00:45 pm by ChrisF »

vfclists

  • Hero Member
  • *****
  • Posts: 1147
    • HowTos Considered Harmful?
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #8 on: June 18, 2013, 10:34:57 pm »
The main point of my question concerns 3 main things.

1. The equivalence of a pointer and a TObject, ie whether the bit pattern that defines a reference is the same bit pattern that a pointer to any kind of object at the same location will be, ie string, record, integer etc.
Pointers and references are different objects in semantic terms - but as current code generation is concerned are the bit patterns that store them identical?

2. Are TObjects moved around under the scenes without programmer involvement, ie within the same thread? ie if after aPtr^ := @desForm is it possible that the memory location @desForm could be changed as a result of some background memory compaction, garbage collection or some other processing? In the example I gave it doesn't work all the time although there is no other processing taking place in between. Is that likely to be due to faulty PtrUint conversions, ie high bit in use or is it due the object being moved around?

3. The other part is whether I need UIntToStr, UIntToHex, StrToUInt etc as the IntXXX cannot handle the whole range of 32bit pointers. In fact if the objects get moved around the pointers will definitely be out of date and nothing can help that. Whether the 'int -> str -> pointer' conversions are correct is the main thing. eg if I converted/cast a pointer on a 32bit system to a 64bit unsigned int there would be no loss and the lower 32bits could be cast back to a pointer safely.

My main goal is to be able to store a 32 or 64 bit pointer as a decimal or hex string and convert it to back correctly and it looks like UIntXXX routines are what I miss.
Lazarus 3.0/FPC 3.2.2

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #9 on: June 19, 2013, 12:37:18 am »
I'm taking the same order of your former explanations.


1. Sorry, but I don't understand what you mean by 'bit pattern': could you explain it more precisely, please ?

 In my former posts, I'm not saying that object references are not pointers, but just that @desform <> TObject(desform) (if we consider only the internal values for them). Which doesn't seem obvious by looking at your own sample code and comments.


2. Any reference to a variable is supposed to be valid (and unchanged) during the 'life' of this variable: would any internal processes change it, it would be impossible to use them (especially when passing them as parameters to other functions/procedures).

Coming back to your sample, all your variables are just 'local' variables. I mean only valid in your procedure; after that, they don't have any more sense, of course.

Is your aPtr variable (i.e. aPtr^ := @desForm ) always valid in your procedure ? Sure, it does (if you are not trying to destroy/recreate desForm, or any other such trick, of course).

Your crashes are not due to any 'internal' pointer process (i.e. modifying the value of an object in memory, for instance). But just because you've wrongly cast your pointer and object variables in the second part of your code.

Have you tried my second modification to see what I mean, for instance ?


3. I can't see any problem due to integer-string conversion, according to your concern. There are no real differences between signed integer and unsigned integer, if you consider their internal representation, anyway.

For instance, strtoint has no problem when dealing with negative numbers (i.e. with the highest bit set). Make your own try with this sample :
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var ul1,ul2: longword;
var s1: string;
begin
  s1:='11111111';
  ul1:=strtoint('$'+s1);
  s1:='FFFFFFFF';
  ul2:=strtoint('$'+s1);
  ShowMessage('ul1='+inttohex(ul1,8)+'  and ul2='+inttohex(ul2,8));
end;

You are still not convinced ? Try with integers, instead:
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var ul1,ul2: integer;
var s1: string;
begin
  s1:='11111111';
  ul1:=strtoint('$'+s1);
  s1:='FFFFFFFF';
  ul2:=strtoint('$'+s1);
  ShowMessage('ul1='+inttostr(ul1)+'  and ul2='+inttostr(ul2));
end;

Of course, -1  <> FFFFFFFF, if we consider strictly these representations. But both of them represent the same number.

**EDIT** : My last samples (about integer-string conversion) have only a sense for a 32 bit CPU, of course; with 4 bytes for integers and longwords. For 64 bits CPU (or for int64 variables on 32 bit CPU), apply the concerned corrections. For instance:
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var ul1,ul2: int64;
var s1: string;
begin
  s1:='1111111111111111';
  ul1:=strtoint64('$'+s1);
  s1:='FFFFFFFFFFFFFFFF';
  ul2:=strtoint64('$'+s1);
  ShowMessage('ul1='+inttohex(ul1,16)+'  and ul2='+inttohex(ul2,16));
end;
« Last Edit: June 19, 2013, 12:47:22 am by ChrisF »

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4603
  • I like bugs.
Re: Code critique required - saving TObjects as strings via Pointer
« Reply #10 on: June 19, 2013, 01:06:56 am »
vfclists, now I understand this is more an academic exercise for yourself to understand the issue. Then it is good. I was worried earlier you put the code into a real application.

ChrisF already gives you good answers, just few points from me.
A reference type is such a useful thing that you should use it always unless there is a good reason to use a pointer type. There is no need to mix those types, like defining a pointer to a reference.

A good reason for a pointer can be the need to use records for very memory critical data structures. A record does not have a self pointer and thus it saves 4 or 8 bytes per instance. Records are used for example for nodes in tree containers and TreeView. They can easily have a million nodes.

Carbage collected languages (actually virtual machines) can move data during execution but Pascal does not have carbage collection or virtual machine.

My main goal is to be able to store a 32 or 64 bit pointer as a decimal or hex string and convert it to back correctly and it looks like UIntXXX routines are what I miss.

You may need a string representation of a pointer for debugging purposes but I cannot imagine any situation where you need to convert a string back to a pointer.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

 

TinyPortal © 2005-2018