Buffer cannot be cloned. Bug?

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Buffer cannot be cloned. Bug?

12 Feb 2024, 17:33

Buffer extends Object and must inherit all of its methods and properties, including the Clone() method. However:

Code: Select all

buf := Buffer(1)
MsgBox 'IsObject: '           . IsObject(buf) . '`n'    ; true
     . 'Has Clone() method: ' . buf.HasMethod('Clone')  ; true

newVar := buf.Clone() ; <———— "Type mismatch" error
What's wrong here? Looks like a bug, or at least an undocumented behavior.
OliverK
Posts: 28
Joined: 08 Mar 2023, 11:55

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 02:27

teadrinker wrote:
12 Feb 2024, 17:33
Buffer extends Object and must inherit all of its methods and properties, including the Clone() method.
"Must"? Are you sure about that?

Methods can be overwritten, at least as far as I know.

Don't know why in this case though..
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 02:38

Buffer Object wrote:In addition to the methods and property inherited from Object, Buffer objects have the following predefined properties.
Nowhere does it say that not all methods are inherited, or any of them are overridden.
OliverK
Posts: 28
Joined: 08 Mar 2023, 11:55

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 03:05

teadrinker wrote:
13 Feb 2024, 02:38
Buffer Object wrote:In addition to the methods and property inherited from Object, Buffer objects have the following predefined properties.
Nowhere does it say that not all methods are inherited, or any of them are overridden.
This may be true but that it "must inherit" all the methods and properties is not correct as far as I know.. semantics.

But you're right of course that it doesn't seem to be documented (funny enough, I intended to use the Clone() method of Buffer too just yesterday.. but didn't.. so I would've stumbled across this myself. Maybe.
just me
Posts: 9542
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 04:22

What would you do with a cloned buffer?

Clone creates a shallow copy of an object, i.e. 'each property or method owned by the object is copied into the clone'. The Buffer object has two special properties, Ptr and Size. The memory block assigned to the buffer doesn't seem to be an own property. So cloning a buffer most probably would generate two buffer objects pointing to the same memory block. Would it make sense?
OliverK
Posts: 28
Joined: 08 Mar 2023, 11:55

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 05:37

just me wrote:
13 Feb 2024, 04:22
What would you do with a cloned buffer?

Clone creates a shallow copy of an object, i.e. 'each property or method owned by the object is copied into the clone'. The Buffer object has two special properties, Ptr and Size. The memory block assigned to the buffer doesn't seem to be an own property. So cloning a buffer most probably would generate two buffer objects pointing to the same memory block. Would it make sense?

I've been thinking about this and came to the conclusion that this must be one of the reasons "Clone()" is not "allowed".. I think that the reference counter for the allocated memory block might impose a problem too if you're "just cloning" a buffer.

Either way, it doesn't seem to be documented?
just me
Posts: 9542
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 05:53

Code: Select all

Error: Type mismatch.

	002: FO := FileOpen(A_ScriptFullPath, "r")
▶	003: FO2 := FO.Clone()
	004: FO.Close()
	005: Exit

Show call stack »
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 06:53

just me wrote: The memory block assigned to the buffer doesn't seem to be an own property. So cloning a buffer most probably would generate two buffer objects pointing to the same memory block. Would it make sense?
But is it forbidden? Let's check it out:

Code: Select all

memBlock := 'someString'
MyBuffer := {}
MyBuffer.ptr := StrPtr(memBlock)
MyBuffer.size := StrLen(memBlock) * 2 + 2

MsgBox 'ptr: ' . MyBuffer.ptr . '`n'
    . 'size: ' . MyBuffer.size

NewBuffer := MyBuffer.Clone()
MsgBox 'ptr: ' . NewBuffer.ptr . '`n'
    . 'size: ' . NewBuffer.size
Descolada
Posts: 1183
Joined: 23 Dec 2021, 02:30

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 09:07

@teadrinker your example doesn't deal with releasing the memory allocated for the string.

If a Buffer were cloned then the reference count should be somehow tracked for the memory as well, since if the original Buffer were to be released along with the memory, then reading it from the cloned Buffer could lead to invalid read/write or return garbage. I can't think of an easy and efficient way to track that reference count. The most sensible approach would be for Clone to create a deep copy, but that would be in conflict with the current documentation and would lead to inconsistencies with other objects.
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 09:49

Isn't throwing an exception a documentation inconsistency? I'm talking in this case about formal fulfillment of OOP principles. Is the type of class extension in AHK inheritance? Obviously, yes. Should methods be inherited in subclass? As I understand, yes. Should inherited methods be executed in the subclass? Yes, unless this is restricted in some explicit way. For example, in Java, the clone() method of the class Object has a "protected" access token. In AHK there is nothing like that, so formally the method must be executed somehow. Am I correct in my reasoning?
Descolada
Posts: 1183
Joined: 23 Dec 2021, 02:30

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 10:05

I think you are correct in your reasoning and perhaps the documentation should be revised. However I don't mind that Clone doesn't work and wouldn't call for implementing it "properly" (that is, shallow-cloning the ptr property), because my aforementioned problems would then be just pushed to the future and make debugging more difficult.
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Re: Buffer cannot be cloned. Bug?

13 Feb 2024, 15:57

Of course, it wouldn't occur to me to clone a buffer in reality. I just wanted to say that the operation of classes should obey the same logic.
just me
Posts: 9542
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Buffer cannot be cloned. Bug?

14 Feb 2024, 06:22

Well, the error seems to be thown here. But I couldn't find out which values are compared in case of a Buffer object.

Apparently, the Clone method is inherited from Object as documented. It just doesn't clone.
lexikos
Posts: 9665
Joined: 30 Sep 2013, 04:07
Contact:

Re: Buffer cannot be cloned. Bug?

01 Mar 2024, 02:28

If Clone wasn't inherited, you would get an error message stating that there is no method by that name.

Object.Prototype.Clone is inherited and can be called, but it cannot construct or clone a Buffer (or a File, Func, Gui, etc.) so it throws a TypeError. Without the type check, it would construct an Object without the specialized binary structure of the Buffer, copy only the "own" properties (if any exist), and set the new object's base to a value which isn't appropriate (since it doesn't have the right binary structure for any Buffer properties or methods to work).

The types which Object.Prototype.Clone cannot handle are the same types which cannot be assigned to {}.Base.
If assigning the new base would change the native type of the object, an exception is thrown. An object's native type is decided by the nearest prototype object belonging to a built-in class, such as Object.Prototype or Array.Prototype. For example, an instance of Array must always derive from Array.Prototype, either directly or indirectly.
Source: Object - Methods & Properties | AutoHotkey v2
Basically every built-in class is a "native type", with the exception that Error and Class objects are the same as Object.

Note that this includes Array and Map, which can only be cloned by Array.Prototype.Clone and Map.Prototype.Clone respectively.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: No registered users and 29 guests