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:213
 
#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:2747
 
  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:207
 
#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:1386
 
#define iferr_return
Definition: resultbase.h:1521
 
  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:222
 
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:176
 
#define iferr_scope_handler
Definition: resultbase.h:1404
 
  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:1584
 
  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:415
 
ResultMem EnsureCapacity(Int requestedCapacity, COLLECTION_RESIZE_FLAGS resizeFlags=COLLECTION_RESIZE_FLAGS::ON_GROW_RESERVE_CAPACITY)
Definition: basearray.h:1320
 
MAXON_ATTRIBUTE_FORCE_INLINE ResultRef< T > Append(ARG &&x)
Appends a new element at the end of the array and constructs it using the forwarded value.
Definition: basearray.h:619
 
#define iferr_ignore(...)
Definition: resultbase.h:1486
 
#define iferr_cannot_fail(str)
Definition: resultbase.h:1465
 
 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