Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Code that crashes AHK_L x32



  • Please log in to reply
26 replies to this topic
iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009
that function crashes AHK_L x32 for me on 3rd call of that function:
upload(input, inputtedMultipleFiles = 0) ; Upload to Imgur using it's API.

{
http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
img := ComObjCreate("WIA.ImageFile")
img.LoadFile(input)
ip := ComObjCreate("WIA.ImageProcess")
data := img.filedata.binarydata
http.Open("POST", "https://api.imgur.com/3/upload")
http.SetRequestHeader("Authorization", "Client-ID " imgurClientID)
http.Send(data)
imgURL := http.ResponseText
http := img := ip := data := input := inputtedMultipleFiles := ""
If (%0% == 0) && clipURL
Return imgURL
}


sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008

EDIT: I'm sorry about the topic's title: I just figured out that I'm using AHK_L Unicode 32-bit


Fixed.

iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009
Thanks, sinkfaze

iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009
I've taken those lines of code from here, but I slightly modified them.
The thing is that the unmodified code by maestrith works fine for me, and my code (a function that I've created is based on the commands for API communication, taken from maestrith's code) crashes the process upon 3rd call. And the crash is always only upon 3rd call: first 2 calls go well.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

What are the requirements for testing this function?  I am not a user of imgur, and have no intention of becoming one.  imgurClientID and clipURL are not defined.  Unless they are declared global (i.e. super-global) outside the function (where I cannot see), they are always empty.

 

All of the basic elements of your script (functions, expressions, ComObjCreate, object syntax, etc.) are heavily used/tested.  Any crash is likely to be in whichever libraries you've called, or caused by using them incorrectly.  In those cases, the Issues forum is not the most appropriate place to get help.

 

Edit - Your code is missing this line from maestrith's original code:

http.SetRequestHeader("Content-Length",size)

However, maestrith's code never sets size.



iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009
Thx for your reply, Lexikos.
I thought you could just analytically define what in that function might cause a crash.

So here is the full list of steps to reproduce the crash.
1. Get GDIp.ahk library.
2. Run my script. It already contains imgurClientID.

To take 1 screenshot 3 PrintScreen hits are required: first hit, move cursor a bit, second hit to lock the recorded area, third hit to take&upload the screenshot.
First 2 screenshots get normally taken and uploaded. But 3rd one causes the script to crash.

And just for the comparison: maestrith's code doesn't cause a crash to me and my old code (which uses the same GDI+ commands that my current code does [but it works with a different hosting and requires the hosting's utility to work]) is also not crashy for me at all.


And yeah, adding http.SetRequestHeader("Content-Length",size) didn't affect anything: the code still crashes script's process.

p.s.: I'll try to ask for help in GDI+ forum topic, but the thing is that the very same gdip calls worked just fine until I modified the 'upload' part in my script.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
✓  Best Answer

When I initially ran your script, it indefinitely waited for the image to exist.  The image was never going to exist, because the path it was trying to save to is invalid:

%USERPROFILE%\AppData\Local\Temp\20130818190301.png

Why are you reading environment variables from the registry?  Your script doesn't have #NoEnv, so you can just use %Temp%.  Alternatively, you could use EnvGet or the built-in %A_Temp%.  I used Temp := A_Temp.

 

I also had to set optimizePNG := 0.  I suggest checking for optipng.exe before attempting to run it.

 

After that, the script crashed on the fourth screenshot.  eventvwr/Application log shows me:

Faulting application name: AutoHotkey.exe, version: 1.1.12.0, time stamp: 0x520b5bb2

Faulting module name: gdiplus.DLL_unloaded, version: 0.0.0.0, time stamp: 0x515bb50a
Exception code: 0xc0000005
Fault offset: 0x704d562e
Faulting process id: 0xe10
Faulting application start time: 0x01ce9bf2beb51aab
Faulting application path: C:\Program Files (x86)\AutoHotkey\AutoHotkey.exe
Faulting module path: gdiplus.DLL
Report Id: 70cab3f4-07e6-11e3-aca5-005056c00008

 

The exception code means Access Violation.  Since it occurred in gdiplus.dll, I presume one of your GDI+ pointers is invalid or your script is corrupting memory used by GDI+.  What this also means to me is that the code in your first post really has nothing to do with the crash.

 

As far as I'm concerned, this is a problem in your script and not AutoHotkey.  I am not interested in debugging it further.



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
http://www.autohotke...y-tic/?p=607484

iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009

When I initially ran your script, it indefinitely waited for the image to exist.  The image was never going to exist, because the path it was trying to save to is invalid:

%USERPROFILE%\AppData\Local\Temp\20130818190301.png

Why is that path invalid?

Why are you reading environment variables from the registry?  Your script doesn't have #NoEnv, so you can just use %Temp%.  Alternatively, you could use EnvGet or the built-in %A_Temp%.  I used Temp := A_Temp.

I didn't know the other way to get the path of windows' built-in %Temp% var so I had to use RegRead to do that.
Thanks for the tip about using just %Temp%.
And no, using %A_Temp% doesn't suit me because %A_Temp% != %Temp%.

I also had to set optimizePNG := 0.  I suggest checking for optipng.exe before attempting to run it.

Thanks for that good idea.

After that, the script crashed on the fourth screenshot.

I did so too and it still crashes on 3rd time.

eventvwr/Application log shows me:
The exception code means Access Violation.  Since it occurred in gdiplus.dll, I presume one of your GDI+ pointers is invalid or your script is corrupting memory used by GDI+.  What this also means to me is that the code in your first post really has nothing to do with the crash.
As far as I'm concerned, this is a problem in your script and not AutoHotkey.  I am not interested in debugging it further.

Thanks for your help, Lexikos. I'm not that good with GDI+, so I'll ask for help there.

iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009
Just for the protocol:
Seems like guest3456 was right about the reason of the script's crash: in my script I had multiple Gdip_Startup() (first of really got into the code by my mistake) and Gdip_Shutdown() calls.
Seems like these are not a very reliable functions: they may work or they may not work for some unknown reasons (even if they get called properly).
My previous script works perfectly fine with multiple calls of Gdip_Startup() & Gdip_Shutdown(), but that code - doesn't work that well.

After fixing my script's code so that it now calls for them only once (which would probably cause memory leakages, since if I kill (not quit, but kill) the script - the 'OnExit' subroutine won't get executed, and that AFAIU will lead a memory leakage) - the script doesn't crash anymore.
It now shows a different error:
http.Send(data)
The server returned an invalid or unrecognized response.
EDIT: seems like it was a two-times error, it doesn't show up anymore.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

And no, using %A_Temp% doesn't suit me because %A_Temp% != %Temp%.

 

It is, unless TMP is set and not equal to TEMP, or both TMP and TEMP are unset.  Even if it returns a different directory to %TEMP%, why would that matter as long as it returns a directory suitable for storing temporary files?

 

 

The GetTempPath function checks for the existence of environment variables in the following order and uses the first path found:

  1. The path specified by the TMP environment variable.
  2. The path specified by the TEMP environment variable.
  3. The path specified by the USERPROFILE environment variable.
  4. The Windows directory.
    Source: GetTempPath function

 

 

Why is that path invalid?

 

AutoHotkey does not expand environment variables in strings, and % is not valid in a path.

 

 

After fixing my script's code so that it now calls for them only once (which would probably cause memory leakages, since if I kill (not quit, but kill) the script - the 'OnExit' subroutine won't get executed, and that AFAIU will lead a memory leakage)

 

You were already calling Gdip_Startup() when the script starts, but not calling Gdip_Shutdown() on exit.  Subsequent calls only increment a counter.  I believe you need to call Gdip_Shutdown() exactly the same number of times to unload GDI+.  Your crashing probably came from calling Gdip_Shutdown() too many times - i.e. you called it when pressing PrintScreen the third time, but never called Gdip_Startup() after that, since the auto-execute section only executes once.

 

Failing to call Gdip_Shutdown() won't leak memory.  Memory is reclaimed by the OS when the process terminates.



iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009

AutoHotkey does not expand environment variables in strings, and % is not valid in a path.

Oh, I've changed the default path of %TEMP% and %TMP% EnvVars in Windows to "R:\Temp", so probably that's why it works fine for me.
So, as far as I understand - I'll have to use GetTempPath() to get the correct path of %TEMP% Windows' EnvVar, right?

You were already calling Gdip_Startup() when the script starts, but not calling Gdip_Shutdown() on exit.  Subsequent calls only increment a counter.  I believe you need to call Gdip_Shutdown() exactly the same number of times to unload GDI+.  Your crashing probably came from calling Gdip_Shutdown() too many times - i.e. you called it when pressing PrintScreen the third time, but never called Gdip_Startup() after that, since the auto-execute section only executes once.

Nope, the issue was a bit different: each 1st PrintScreen hit was calling Gdip_Startup(). I just wrongly added another Gdip_Startup() call on startup: comment it out (the whole first block that starts with "If !pToken := Gdip_Startup()") and there would be as many gdip_shutdown()'s as gdip_startup()'s, but the script would still crash upon 3rd call.
The very same gdip-related code works perfectly fine in my old script, who also called gdip_startup() every time the drawing started and called gdip_shutdown every time it was time to clear the drawing. No crashes. Works stable.
The only part that I've changed is actually the communication with the server: earlier I used a different pic-hosting and I used their util and the script was just automatizing the button clicks in that util. And now the script uses a different pic-hosting and uses ComObjs to communicate with that server using their API.
That's what was really strange and that confused me so much, that I didn't thing that GDI+ could be the reason of the crash and that's why I've created this topic.

Failing to call Gdip_Shutdown() won't leak memory.  Memory is reclaimed by the OS when the process terminates.

Oh, good to know that I don't need to worry about that. [That also actually means, that I can remove Gdip_Shutdown() from my script at all, since the OS will nurse me anyways grin.png]

Thanks for your help, Lexikos.

img.imageResizerActiveClass{cursor:nw-resize !important;outline:1px dashed black !important;} img.imageResizerChangedClass{z-index:300 !important;max-width:none !important;max-height:none !important;} img.imageResizerBoxClass{margin:auto; z-index:99999 !important; position:fixed; top:0; left:0; right:0; bottom:0; border:1px solid white; outline:1px solid black;}

Edited by iDrug, 20 August 2013 - 08:40 PM.


guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

Just for the protocol:
Seems like guest3456 was right about the reason of the script's crash: in my script I had multiple Gdip_Startup() (first of really got into the code by my mistake) and Gdip_Shutdown() calls.
Seems like these are not a very reliable functions: they may work or they may not work for some unknown reasons (even if they get called properly).
My previous script works perfectly fine with multiple calls of Gdip_Startup() & Gdip_Shutdown(), but that code - doesn't work that well.


you should not claim that functions are unreliable when you are using them incorrectly. if it worked correctly in previous scripts, you got lucky. you are using it wrong so your previous script is badly coded as well. i have not seen one example yet where it was necessary to have multiple, SIMULTANEOUS, Gdip_Startup() calls needed

for now, its probably best for you to assume that any errors you encounter are due to YOUR CODE, and not due to AHK or GDI+ or any other library that you are working with. you prematurely posted this thread in this forum as if there was a bug with AHK itself, and now you are accusing GDI+ of the problem of being unreliable

your thread should be in the "Support" section where you are asking other people for help: "What am I doing wrong?" instead of accusing everything else of being broken

apologies if i'm being harsh but the truth is the truth

iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009

i have not seen one example yet where it was necessary to have multiple, SIMULTANEOUS, Gdip_Startup() calls needed

There were no simultaneous Gdip_Startup() calls in my both scripts (one that works fine and one that was crashy). The block that starts with "If !pToken := Gdip_Startup()" got into my code just when I was uploading it to show it to you, my local version didn't have that block, but the crash still appeared. Please, do disregard that block.

for now, its probably best for you to assume that any errors you encounter are due to YOUR CODE, and not due to AHK or GDI+ or any other library that you are working with. you prematurely posted this thread in this forum as if there was a bug with AHK itself, and now you are accusing GDI+ of the problem of being unreliable

I assumed that from the beginning: the topic's name says that my code is crashing AHK process. My code. Not gdi+ or ahk.

your thread should be in the "Support" section where you are asking other people for help: "What am I doing wrong?" instead of accusing everything else of being broken
apologies if i'm being harsh but the truth is the truth

No offense taken: since the crash is now resolved - I agree that it's time to ask in "Support" section, that's why I even marked this topic as "solved".

iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009
p.s.: I'm very grateful to both of you (Lexikos and guest3456), and not only for resolving the main issue (crash), but for your other suggestions about some specific parts of code.