 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
Estecka How do I cheat?
Reputation: 0
Joined: 05 Mar 2022 Posts: 4 Location: France
|
Posted: Sat Mar 05, 2022 3:57 pm Post subject: pcall won't catch "is an invalid <type>" err |
|
|
Hi,
I was only recently introduced to lua, so I might be missing something obvious.
I was working on some boilerplate lua script loop.
Because I've often caused some dramatic looping errors before, I wanted to set up some kind of catch-all error handler, that would abort the loop if anything goes wrong :
| Code: | function Update()
-- Script logic will go here.
print("Before error");
AddressList["HP"].value = nil; -- Should throw an error.
print("After error");
end
LuaLoop = createTimer();
LuaLoop.interval = 1000/60;
LuaLoop.Enabled = false;
LuaLoop.onTimer = function ()
local ok, msg = pcall(Update);
print("Ok:", (ok and 'true' or 'false'), "Msg:", msg);
if (not ok) then
LuaLoop.setEnabled(false);
print("Lua Script Loop aborted");
end
end
|
The error thrown in the script logic is `Error:"" is an invalid float`
I would expect pcall to catch this error, but the error passes right through it; nothing in the code after pcall is evaluated, as if pcall itself had thrown an error.
What can I do to catch this error properly ?
Eventually, if I don't manually abort the loop, the repeating error will cause a `C stack overflow`. This one is caught in pcall and aborts the loop as expected, but at this point it's already too late; the Lua Script Table is busted, and I need to completely restart Cheat Engine in order to use it again.
_________________
Y s'taient cachés les steaks hachés. |
|
| Back to top |
|
 |
TheyCallMeTim13 Wiki Contributor
Reputation: 51
Joined: 24 Feb 2017 Posts: 976 Location: Pluto
|
Posted: Sat Mar 05, 2022 5:44 pm Post subject: |
|
|
I'd say it's just due to different error handling with in CE's code. I don't think pcall is setup to catch all errors it's more for catching lua errors not C level stuff. I'd say focus more on proper error handling and not trying to use a catch all. So have checks to make sure the value is of the right type and throw an error if it's not.
_________________
|
|
| Back to top |
|
 |
Estecka How do I cheat?
Reputation: 0
Joined: 05 Mar 2022 Posts: 4 Location: France
|
Posted: Sun Mar 06, 2022 1:06 pm Post subject: |
|
|
Sure, type-checking will fix the issue right here and right now in this specific script, but that's it, and that's not quite what I'm looking for.
Writing a script that doesn't fail is good, but walking out of this with the assumption I'll never again write a script that fails in the exact same way (or any other way for that matter) would be presumptuous of me. I need that catch-all handler not to "fix" the error, but as a fail-safe, because the consequences for failure here are quite spectacular, and I want to attenuate them.
Aside, I'm thinking that if the only way to throw a proper error, is to wrap all value assignation with some type checking, maybe this check would deserve to be built into the setter for `MemoryRecord.value` ?
| Quote: | | I don't think pcall is setup to catch all errors it's more for catching lua errors not C level stuff. |
There's something I don't get here. Does "C stackoverflow" -the one error that is actually being caught here-, not count as a C level error ?
Conversely, "is an invalid float" is a runtime error I'd expect to come from Lua, not from a strong-typed low-level languages like C; pure C doesn't even have a mechanism for throwing this kind of errors as far as I know.
_________________
Y s'taient cachés les steaks hachés. |
|
| Back to top |
|
 |
TheyCallMeTim13 Wiki Contributor
Reputation: 51
Joined: 24 Feb 2017 Posts: 976 Location: Pluto
|
Posted: Sun Mar 06, 2022 1:40 pm Post subject: |
|
|
When I said C level, I was making a generalisation. CE is written with pascal not Lua, thus when you set "SomeMemeoryRecord.Value" it's using pascal code to do that. It's just that the memory record object is exposed to lua.
And you can wrap an entire C# program in a try call, but any programmer worth their weight will tell you not to do anything like that and to work on proper error handling.
And it seems like the error is handled in pascal, that's why you get the invalid float error. But the pcall doesn't catch it and the timer keeps spamming the error. And you have the interval set to "16.6" milliseconds so it's spamming it fast and hard. And when I tested the code the "C stack overflow" didn't actually cause the lua to catch it either and it was that the whole script was stopped. But of course when you start talking stack overflow errors, I would expect odd behavior and for things to not always respond the same. Basically the call stack memory is being exceeded so the system kills whatever is causing it, thus the timer seems to stop. But the error message was never printed for me.
_________________
|
|
| Back to top |
|
 |
Estecka How do I cheat?
Reputation: 0
Joined: 05 Mar 2022 Posts: 4 Location: France
|
Posted: Sun Mar 06, 2022 3:01 pm Post subject: |
|
|
The key difference between this and a regular C# program, is that any uncaught exception in a regular program would immediately kill the entire process, which is the best outcome we could hope for anyway. Here, this is not the case, the timer keeps running, doingspaghetti monsterknows what and spamming the error; ironically simply trying to replicate the usual behaviour of not having a try-catch block at the root of a program, requires here some kind of root try-catch.
Again, yes, proper error handling is preferable, but it only works after I've identified the errors that need to be handled. Until I know what kind of error I will need to handle or before I even realize there is an error I need to handle, this is the best I can get; and I can never be certain that all potential errors are being handled.
In any case, I've kept mulling it over, and here's a solution I came up with that should work with any error, catchable or not :
| Code: |
UncaughtError = false;
LuaLoop.onTimer = function()
if (UncaughtError) then
-- terminate timer
return;
end
UncaughtError = true;
-- script logic
UncaughtError = false;
end
|
This does the error checking in the next iteration of the loop instead. A bit hacky, but it gets the work done.
| Quote: | | when I tested the code the "C stack overflow" didn't actually cause the lua to catch it |
Odd, a "C stackoverflow" is definitely being caught by pcall on my side; at the very least I see it in the print I do right after pcall.
I'd send over the exact cheat table I using it in, but for some reason the size limit for uploading *.ct is only 8 Bytes...
_________________
Y s'taient cachés les steaks hachés. |
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Sun Mar 06, 2022 3:11 pm Post subject: |
|
|
There are Lua errors and there are pascal exceptions. It seems like the Lua environment doesn't care about pascal exceptions.
I guess you could try to acquire a critical section at the start of the loop and release it at the end if there aren't any errors. If you can't acquire it at the start, then it clearly wasn't released, and you can stop the timer early there.
(this is more or less what you're doing with UncaughtError)
I don't know what you're doing, but if pcall really seems like the best solution, you're probably doing something wrong. In all my experience with using Lua in CE, you really don't need to be handling errors like this. The only circumstance I can think of is if you're writing a library that uses some user-provided code as a callback or something. Even then, in most cases, it's fine to not use pcall.
This sounds stupid but the best error handling strategy really is to not generate errors in the first place. e.g. if you're assigning some numeric value to MemoryRecord.Value, make sure the string is a number first.
| Code: | local n = tonumber(newValue)
if n then
memrec.Value = tostring(n)
end |
When writing tables, stuff happens. CE might crash or lock up when you mess up. It doesn't matter how "safe" you try to make your code with pcall or other methods- it'll happen regardless. Enable auto-saving and you'll be fine.
Lua is a scripting language. If you want stronger guarantees like type safety and good error handling, use some other language.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
Estecka How do I cheat?
Reputation: 0
Joined: 05 Mar 2022 Posts: 4 Location: France
|
Posted: Sun Mar 06, 2022 3:53 pm Post subject: |
|
|
| Quote: | | The only circumstance I can think of is if you're writing a library that uses some user-provided code as a callback or something. |
Well yes, this pretty much the mindset I'm going with here.
I'm not particularly concerned about CE crashing without saving, but I'll still try to ease out the burns where I know one tend to happen.
| Quote: | | If you want stronger guarantees like type safety and good error handling, use some other language. |
What other languages are there one can use with CE in that way ?
I mostly went with Lua because it was the most readily available, and the most noticeably advertised within CE's menus and UI.
_________________
Y s'taient cachés les steaks hachés. |
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25807 Location: The netherlands
|
Posted: Sun Mar 06, 2022 3:56 pm Post subject: |
|
|
you can use a hybrid of lua and any other language.
e.g a plugin in c# and for gui access in CE use lua as a control interface
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|