Exception handling: Difference between revisions

From Bohemia Interactive Community
mNo edit summary
(Some wiki formatting, Add alt syntax, Add Introduced with category)
 
(14 intermediate revisions by 9 users not shown)
Line 1: Line 1:
In Armed Assault exception handling is an implemented system of special scripting commands ([[try]], [[catch]] and [[throw]]), which allows your scripts to create and to react to exceptions.
{{GVI|arma1|1.00}}
Standard construction is:


try {
{{arma1}} introduced exception handling through the [[try]], [[catch]] and [[throw]] scripting commands, allowing scripts to create and react to exceptions.
    //block, that can throw exception
    if (_name == "") then {
        throw "no name"
    } else {
        TitleText [format["Good morning, Captain %1.", _name], "PLAIN DOWN"]
        ~1
        TitleText [_name, "PLAIN DOWN"]
}<br>
catch {
    //block, that processes an exception
    if (_exception == "no name") then {
        echo "Name wasn't entred"
        TitleText ["And the name isn't", "PLAIN DOWN"]
    }
}


Standard structure:
<sqf>
try // code block that can throw exception
{
if (_name == "") then { throw "no name"; }; // this exits the [[try]] block and enters the [[catch]] block below
if (_name == "") throw "no name"; // since {{arma3}} v1.54


titleText [format ["Good morning, Captain %1.", _name], "PLAIN DOWN"];
}
catch // code block that processes an exception
{
if (_exception == "no name") then
{
hint "Name was not entered";
titleText ["Good morning, anonymous Captain.", "PLAIN DOWN"];
};
};
</sqf>


----


{{Feature|important|
{{Name|rv}} scripting commands do '''not''' create SQF exceptions by themselves if they encounter an illegal situation,
they throw a '''''compilation''''' exception that cannot be caught by this try-catch structure explained here.


Probably is this possible too:
The following would therefore '''not''' create a catchable exception:
<sqf>
_divider = 0;
try { a = 1 / _divider; } // SQF error happens here already
catch { hint "illegal operation"; }; // useless
</sqf>


{{Box File|[] fireBomb.sqs|<pre>
The proper way:
_car = _this select 0
<sqf>
if (crew _car == 0) then {
_divider = 0;
    throw "vehicle empty"
try { if (_divider == 0) then { throw "div0"; }; a = 1 / _divider; }
} else {
catch { hint "illegal operation"; };
    if (3 < random 10) then {
</sqf>
        throw "bomb failed"
}}
    } else {
        _car setDammage 1
        if (alive Guba) then {
            throw "bastard still alive"
        }
    }
}     
</pre>}}


try {
    TitleText ["Sgt. Detritus: I get bomb to his car ;-)", "PLAIN DOWN"]
    [jeepOne] exec "fireBomb.sqs"
    TitleText ["Sgt. Detritus: He is dead!", "PLAIN DOWN"]
}<br>
catch {
    if (_exception == "vehicle empty") then {
        TitleText ["Sgt. Detritus: He have luck, but next time I'll kill him!", "PLAIN DOWN"]
    } else {
        TitleText [format["Sgt. Detritus: Some strange error appears... %1... hmm... another time I'll get him!", _exception], "PLAIN DOWN"]
}


In OFP, "exec" was asynchronous - think spawning another thread. (ArmA will make this slightly more explicit with the command spawn) As such, an exception won't unwind into the caller so that it can be caught and used there. Though firebomb.sqs would preferrably be inlined to begin with, using "call preprocessfile firebomb.sqf" would be getting you the effect you want. Besides, it could go into "he is dead" before firebomb.sqs' first line got executed.
[[Category: Scripting Topics]]
 
[[Category:Introduced with Armed Assault version 1.00]]
There are, however, several things about the piece of code above worthy of criticism. First of all, the handler is a catch(anything) (as ofpscript forces it to be) but the handler assumes it to be a string. {if typeof _exception != "string" throw } as the first command in the handler should properly rethrow the exception so it can be handled even further out. (The last throw might require _exception as a parameter.) 
 
The second, and bigger problem, is that the exception handling is used as a way of returning values. Exceptions ''should'' be used exclusively for runtime handling of error conditions. At least traditionally, this was so because exceptions are rather "expensive" in use, but generally speaking, the only proper reason for such usage is the lack of other suitable ways of returning results.  It's good form, and helps maintainability.
 
Exceptions are most useful when different people work on interacting pieces of code.
 
--[[User:MaHuJa|MaHuJa]] 07:29, 23 August 2006 (CEST)
 
[[Category:ArmA: Scripting]]

Latest revision as of 18:15, 7 January 2026

Logo A1 black.png 1.00

Armed Assault introduced exception handling through the try, catch and throw scripting commands, allowing scripts to create and react to exceptions.

Standard structure:

try // code block that can throw exception { if (_name == "") then { throw "no name"; }; // this exits the try block and enters the catch block below if (_name == "") throw "no name"; // since Arma 3 v1.54 titleText [format ["Good morning, Captain %1.", _name], "PLAIN DOWN"]; } catch // code block that processes an exception { if (_exception == "no name") then { hint "Name was not entered"; titleText ["Good morning, anonymous Captain.", "PLAIN DOWN"]; }; };


Real Virtuality scripting commands do not create SQF exceptions by themselves if they encounter an illegal situation,

they throw a compilation exception that cannot be caught by this try-catch structure explained here.

The following would therefore not create a catchable exception:

_divider = 0; try { a = 1 / _divider; } // SQF error happens here already catch { hint "illegal operation"; }; // useless

The proper way:

_divider = 0; try { if (_divider == 0) then { throw "div0"; }; a = 1 / _divider; } catch { hint "illegal operation"; };