Problem in rewriting of VarSetCapacity to BufferAlloc

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
aseiot
Posts: 80
Joined: 05 Mar 2017, 04:25

Problem in rewriting of VarSetCapacity to BufferAlloc

10 Sep 2019, 10:59

I am trying to rewrite VarSetCapacity to BufferAlloc as suggestion in document, but encounter some problems. Could anyone be help.

Code: Select all

Gdip_Startup()
{
	pToken := 0
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), NumPut("UInt", 1, &si)
	if DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "UPtr", 0)		; ok
		PromptMsg("Error in loading GDIP")
	return pToken
}
But this will fail:

Code: Select all

Gdip_Startup()
{
	pToken := 0
	si := BufferAlloc(A_PtrSize = 8 ? 24 : 16), NumPut("UInt", 1, si)
	if DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", si, "UPtr", 0)			; failed
		PromptMsg("Error in loading GDIP")
	return pToken
}
Similar problem in Create a BUTTON_IMAGELIST structure.
Following is part of code from ImageButton class of justme

Code: Select all

		; Create a BUTTON_IMAGELIST structure
		VarSetCapacity(BIL, 20 + A_PtrSize, 0)		; work
		;~ BIL := BufferAlloc(20 + A_PtrSize)		; not work
		NumPut("Ptr", HIL, BIL)
		Numput("UInt", BUTTON_IMAGELIST_ALIGN_CENTER, BIL, A_PtrSize + 16)
		; Hide buttons's caption
		Btn.Text := ""
		Btn.Opt("+" BS_BITMAP)
		; Assign the ImageList to the button
		SendMessage(BCM_SETIMAGELIST, 0, 0,HWND)
		SendMessage(BCM_SETIMAGELIST, 0, &BIL,HWND)			; work
		;~ SendMessage(BCM_SETIMAGELIST, 0, BIL,HWND)		; code for BufferAlloc, failed
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

10 Sep 2019, 11:52

i vaguely recall this working in a103

but be aware of https://www.autohotkey.com/boards/viewtopic.php?f=76&t=62000&p=263391, whenever this ends up getting fixed
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

10 Sep 2019, 12:49

When bufferalloc was added it didn't zero initialise, I don't know if this was fixed, if not, that could cause issues.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

10 Sep 2019, 12:59

it doesnt in a103
it does in a104
Last edited by swagfag on 18 Sep 2019, 08:03, edited 1 time in total.
User avatar
aseiot
Posts: 80
Joined: 05 Mar 2017, 04:25

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

12 Sep 2019, 09:46

Helgef wrote:
10 Sep 2019, 12:49
When bufferalloc was added it didn't zero initialise, I don't know if this was fixed, if not, that could cause issues.
Thanks for this info.
Document wrote:All bytes within the buffer are zero-initialized.
I thought it had zero-initialized, but it didn't, after check the source.
lexikos
Posts: 9665
Joined: 30 Sep 2013, 04:07
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

18 Sep 2019, 03:11

BufferAlloc does not zero-initialize in any version. This was not originally intentional, hence the documentation not matching the behaviour.

Buffer.Size:= zero-initializes any new bytes.

My original intention was to zero-initialize all bytes, but the performance impact is bigger than I thought. I will most likely add a FillByte parameter, the same as VarSetCapacity.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

18 Sep 2019, 04:23

I will most likely add a FillByte parameter, the same as VarSetCapacity.
:thumbup:
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

18 Sep 2019, 09:22

Adding the FillByte parameter to the BufferAlloc function seems most appropriate.
Another option, which does not have to be exclusive, is to remove the fill from the Size property and add a MemFill(FillByte,Target,Bytes,Offset) function. Having a function dedicated specifically to this is very useful in certain cases, such as if we want to reuse an existing buffer to pass as a structure, or if we have a very large buffer and only need to fill a part of it.
lexikos
Posts: 9665
Joined: 30 Sep 2013, 04:07
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

20 Sep 2019, 01:44

Would you use it with something other than a Buffer?

I think that zero-initializing a struct is by far the most common use for FillByte or similar. For anything else, calling RtlFillMemory or memset via DllCall is fairly trivial.

Adding a FillByte parameter to BufferAlloc also simplifies translation from VarSetCapacity.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

25 Sep 2019, 13:40

I am not sure I understand the reason for that question. As I said, the function can be used to reuse an existing Buffer or a part of it, regardless of how it was allocated.
Passing an object with properties Ptr and Size can ensure that the function does not write to an invalid memory location.
I agree that doing MemFill or MemCopy with DllCall is trivial.

Thanks for the update. :wave:
lexikos
Posts: 9665
Joined: 30 Sep 2013, 04:07
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

26 Sep 2019, 17:25

If it's only used with Buffer, why a function rather than a method?

You've said how and why a Buffer (or Buffer-like) would be used with it, but I was asking about about every other kind of target.

Also, Buffer objects can already be reused without this function. If it requires initialization, you must do that before first use as well, so this does not help (just) for reuse. If it does not require initialization, this function is irrelevant.

Edit: Maybe I missed the point of "regardless of how it was allocated". In what cases would it not be allocated by BufferAlloc (and therefore not actually be a Buffer)?
User avatar
kczx3
Posts: 1648
Joined: 06 Oct 2015, 21:39

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

26 Sep 2019, 20:28

Possibly the lParam from an OnNotify handler? Though I guess that’s just an address
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

28 Sep 2019, 02:48

I don't see why it should be limited only to the Buffer object. Target can be any object with properties Ptr and Size, or any memory address.
If a Copy(To) method is added, a CopyFrom method should also be added. For example, if we retrieve data from the clipboard (GlobalAlloc) and want to copy it into our Buffer.
I know that here we are talking about MemFill and not MemCopy, but if in the future it is planned to add, it would be consistent with MemCopy.
Also, these functions could be added without the need to implement the Buffer object in v1.
lexikos
Posts: 9665
Joined: 30 Sep 2013, 04:07
Contact:

Re: Problem in rewriting of VarSetCapacity to BufferAlloc

28 Sep 2019, 04:18

As a method of the Buffer object,
  • it is restricted to a known valid memory range (the buffer) and can never directly corrupt heap memory or cause an access violation exception (of the type that exhibits as a "crash").
  • parameter order can be optimized for the Buffer object. (Well, I suppose if the function would be mostly used with the Buffer object, parameter order can be optimized for the Buffer object anyway.)
  • it will not add clutter to the main list of functions. I probably only thought of that as an issue because I do not feel a need to have this function or method in the first place (and that alone is the reason I don't intend to implement it right now).
Hypothetically, if MemFill would be passed a Buffer object 99% of the time, it's probably not worth having as a separate function. Hence my original question.
For example, if we retrieve data from the clipboard (GlobalAlloc) and want to copy it into our Buffer.
I envisioned BufferAlloc(Size) and BufferFrom(Ptr, Size) or similar, but haven't added the latter as it wasn't directly relevant to what I was doing. ClipboardAll(Ptr, Size) already serves that purpose, if you don't mind ignoring what type() says. Of course, maybe you want to reuse a Buffer.

General memory manipulation functions might come in handy some time, but if you're capable of using them correctly and safely, you're probably capable of doing it via DllCall.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: TAC109 and 14 guests