Sign in Join

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

Mailing lists / fpc-pascal / 2009-06

Generic a "Clone" method

5 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

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

Torsten Bonde Christiansen

Hi.

I was wondering if it is posible to make this type of construct for creating a generic Clone method:

(I put it in pastebin): http://pastebin.com/fb495ed7

Explained in words - I'm trying to make a clone method that should be able to copy the content of private variables to a destination object. Naturally this destination would have to be of the same class as the original, but is it posible to determine the size of used space in each derived class, simply by using Sizeof(...). Or do I need to create a seperate clone method for each individual derived class.

If it is posible, what memory copy function should I use?

Kind regards,
Torsten Bonde Christiansen.

Martin Friebe
to Torsten Bonde Christiansen
Torsten Bonde Christiansen wrote 15 lines
Hi. I was wondering if it is posible to make this type of construct for creating a generic Clone method: (I put it in pastebin): http://pastebin.com/fb495ed7 Explained in words - I'm trying to make a clone method that should be able to copy the content of private variables to a destination object. Naturally this destination would have to be of the same class as the original, but is it posible to determine the size of used space in each derived class, simply by using Sizeof(...). Or do I need to create a seperate clone method for each individual derived class. If it is posible, what memory copy function should I use?

There is Object.InstanceSize, which sounds as if it may be what you are looking for.
But you have a bigger problem than that.

If any member (object variable) is of a ref-counted type (that is strings and dynamic arrays), then any "memory copy" will mess up.

Because in the objects memory, there only are the pointers to the data of strings, and dyn-arrays. If you copy those pointer by hand, then the reference-counts in the actual string or dyn-array are not updated. this leads to at least 2 problems.

1)
If the original object was the only holder (or last remaining) of a reference to this string, and your original or new object is destroyed, the ref-count goes down to zero => the string is freed, and the other object points to unallocated memory, or meory allocated to some new/other data) => crash

2)
Again if, your old object was the only holder, then the ref-count is still 1. Strings are "copy on modify", => 2 copies of a string share memory until one is changed (in which case a copy is made). The need for making the copy is determined by ref-count > 1.
Your ref-count is 1 => no copy is made, the new object is updating the strings of the old object too

Best Regards
Martin

Torsten Bonde Christiansen
to Martin Friebe
Martin Friebe wrote
There is Object.InstanceSize, which sounds as if it may be what you are looking for. But you have a bigger problem than that.

Thanks - i'll try that.

Show quoted text 21 lines
If any member (object variable) is of a ref-counted type (that is strings and dynamic arrays), then any "memory copy" will mess up. Because in the objects memory, there only are the pointers to the data of strings, and dyn-arrays. If you copy those pointer by hand, then the reference-counts in the actual string or dyn-array are not updated. this leads to at least 2 problems. 1) If the original object was the only holder (or last remaining) of a reference to this string, and your original or new object is destroyed, the ref-count goes down to zero => the string is freed, and the other object points to unallocated memory, or meory allocated to some new/other data) => crash 2) Again if, your old object was the only holder, then the ref-count is still 1. Strings are "copy on modify", => 2 copies of a string share memory until one is changed (in which case a copy is made). The need for making the copy is determined by ref-count > 1.

Can this be avoided by using the "UniqueString(..)" method?

Show quoted text 12 lines
Your ref-count is 1 => no copy is made, the new object is updating the strings of the old object too Best Regards Martin _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
JoshyFun
to Torsten Bonde Christiansen

Hello FPC-Pascal,

Tuesday, June 16, 2009, 2:27:07 PM, you wrote:

TBC> Martin Friebe wrote
> There is Object.InstanceSize, which sounds as if it may be what you > are looking for. > But you have a bigger problem than that.

TBC> Thanks - i'll try that.

From my point of view a generic clone method can not and must not be written, but for your purposes, this means your own classes, you can derive a "TClonableObject" from "TObject" and use it for the new classes, this function must be virtual, so you can specialize the default clone method in each class when ref counted variables are present or custom records, arrays, etc and of course alloc'ed pointers. Something like:

function TClonedClonedObject.Clone(): TClonableObject;
begin
     Result:=Inherited Clone();
     //Now fixup the ref.counted strings in example, but
     //you must use pointers to avoid automatic string dispose.
end;

For sure it is not a generic function ;)

Best regards, JoshyFun
Martin Friebe
to Torsten Bonde Christiansen: Thanks - i'll try that. Can this be avoided by using the "UniqueString(..)" method?
Torsten Bonde Christiansen wrote 25 lines
Martin Friebe wrote: > > If any member (object variable) is of a ref-counted type (that is > strings and dynamic arrays), then any "memory copy" will mess up. > > Because in the objects memory, there only are the pointers to the > data of strings, and dyn-arrays. If you copy those pointer by hand, > then the reference-counts in the actual string or dyn-array are not > updated. > this leads to at least 2 problems. > > 1) > If the original object was the only holder (or last remaining) of a > reference to this string, and your original or new object is > destroyed, the ref-count goes down to zero => the string is freed, > and the other object points to unallocated memory, or meory allocated > to some new/other data) => crash > > 2) > Again if, your old object was the only holder, then the ref-count is > still 1. Strings are "copy on modify", => 2 copies of a string share > memory until one is changed (in which case a copy is made). The need > for making the copy is determined by ref-count > 1. Can this be avoided by using the "UniqueString(..)" method?

If you know where the strings are...; but then it's no longer unique.

You can try something else, but i have no idea where it leads too, or if its usable (in objpas mode)

type
 TFoo = object
 private
 public
 end;

Acts like a record, with methods, kind of.....

anyway
var a, b: TFoo

  a:=b;

Takes care of everything.

BUT those "objects" are like records. they do not allocate ne meory, each time you create them, they alloc mem when you *declare* them

if you pass them to a function in the arg list, they get copied. ( with "class" the pointer gets copied, because class is in reality a pointer.

  So you could declare
 TRealFoo = ^TFoo;

then write your constructor to return the pointer, every access would need the dereference of course => massive change to syntax.

and so on.
If it is for you, you have to RT(F)M yourself....

Martin