About
The MAXON API uses a custom error reporting system. In case of an error, a function can return an error object. The return value and the error object are stored in a maxon::Result object. Within a function scope it is also necessary to handle errors returned by sub-functions.
Return Errors
A function that returns a maxon::Result object can either return just the plain return value or a complex error object. This error object can contain detailed information on the error that occurred. For more details on the maxon::Result class see Error Result. For a list of default error types see Error Types.
{
if (RollDice(number) == false)
return number;
}
Definition: resultbase.h:766
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:188
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:67
Functions that do not return any value can return Result<void>:
{
if (number == nullptr)
*number = *number + 1;
}
return OK
Definition: apibase.h:2667
It is possible to create an error object before it is needed to increase the performance in speed critical tasks:
- MAXON_ERROR_PREALLOCATE: Macro used to preallocate an error object.
{
if (pos < 0.0 || pos > 1.0)
return g_sampleArgumentError;
}
void Py_ssize_t * pos
Definition: dictobject.h:50
float Float32
32 bit floating point value (float)
Definition: apibase.h:182
#define MAXON_ERROR_PREALLOCATE(errorName, init)
Definition: errorbase.h:434
Error Scope
Within a given error scope one must define how errors returned by sub-functions are handled.
- Note
- An error returned by a function must be handled explicitly. Ignoring the returned error object will result in a compile error on certain systems.
Best practice to handle errors is typically to declare an error scope and to simply return the error returned by a sub-function:
- iferr_scope: Declares an error scope.
- iferr_scope_handler: Executes the defined code when called with iferr_return.
- iferr_scope_result: Can be used in a finally block to check the error state.
In such an error scope one can simply return from the function if an error occurred in a sub-function:
- iferr_return: If an error occurred, this error is returned.
{
return randomFloat;
}
maxon::Float Float
Definition: ge_sys_math.h:66
The maxon namespace contains all declarations of the MAXON API.
Definition: autoweight.h:14
#define iferr_scope
Definition: resultbase.h:1374
#define iferr_return
Definition: resultbase.h:1465
If a simple error scope is declared with iferr_scope, the attribute iferr_return will return from the function returning the detected error. In contrast, iferr_scope_handler allows to define a function that is called before iferr_return will return.
- Note
- When called with iferr_return, the return value of iferr_scope_handler is used as the return value of the function.
Compare also Finally.
{
{
return 0.0;
};
return randomFloat;
}
Float64 Float
Definition: apibase.h:197
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:176
#define iferr_scope_handler
Definition: resultbase.h:1392
It is also possible to simply check if a called function returned an error or not.
- iferr: Checks if the given function returned an Error. Defines maxon::ErrorPtr
err
that can be returned.
- ifnoerr: Checks if the given function returned no error. Defines maxon::NoErrorPtr.
{
iferr (randomNumber = GetRandomNumber())
{
return err;
}
return randomFloat;
}
#define iferr(...)
Definition: errorbase.h:388
If a new error is created within a function it is typically just returned. If one wants iferr_scope_handler to be called before one must use iferr_throw:
- iferr_throw: Throws an error that is caught in iferr_scope_handler.
{
{
return 0.0;
};
if (scale == 0.0)
return randomFloat;
}
#define iferr_throw(ERR)
Definition: resultbase.h:1528
In some cases an error can be ignored. Such cases must be marked and explained explicitly:
- Note
- Use these attributes only if the error can be ignored or there is no way of handling the error. Always describe the reason why this macro was used.
{
}
Py_ssize_t i
Definition: abstract.h:645
Py_ssize_t count
Definition: abstract.h:640
Definition: basearray.h:412
ResultMem EnsureCapacity(Int requestedCapacity, COLLECTION_RESIZE_FLAGS resizeFlags=COLLECTION_RESIZE_FLAGS::ON_GROW_RESERVE_CAPACITY)
Definition: basearray.h:1480
MAXON_ATTRIBUTE_FORCE_INLINE ResultRef< T > Append(ARG &&x)
Definition: basearray.h:677
#define iferr_ignore(...)
Definition: resultbase.h:1430
#define iferr_cannot_fail(str)
Definition: resultbase.h:1409
Error handling can be limited to a sub-scope within a function by using a lambda:
{
{
if (scale == 0.0)
return randomFloat;
};
iferr (randomFloat = GetFloat())
return randomFloat;
}
Error Handling and Resource Management
The attribute iferr_return allows to return from a function when an error was detected. This could lead to issues with resources that have to be managed and freed within the function scope. For example a certain resource must be freed when the function is ending. Allocated objects and memory are best handled using References.
For more complex situations one can use either iferr_scope_handler or finally:
- The resource clean-up can be handled with iferr_scope_handler. If this is the case any custom error returned from within the function must use iferr_throw to make sure that iferr_scope_handler is called before the function is left.
- The resource clean-up can be handled with finally.
{
{
FreeInternalData();
return err;
};
if (GetInternalSuccess() == false)
FreeInternalData();
}
OK
Ok.
Definition: ge_prepass.h:0
{
finally
{
FreeInternalData();
};
if (GetInternalSuccess() == false)
}
Further Reading