uCalc API Version: 2.1.3-preview.2 Released: 6/17/2026
Warning
uCalc API Preview Release Notice:The documentation describes the intended behavior of the API. The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.
Managing Parser Instances & Lifetime
Product:
Class:
Explains the critical patterns for managing uCalc instance memory and lifetime to prevent resource leaks, covering both automatic (RAII/using) and manual release strategies.
Remarks
⚙️ Managing Parser Instances & Lifetime
A uCalc instance is more than just an object; it's a complete, sandboxed parsing and evaluation engine with its own state, including variables, functions, and settings. Because the core engine is written in high-performance C++, proper management of its memory and lifetime is one of the most critical aspects of using the library correctly.
This guide explains why lifetime management is necessary and covers the two primary strategies for preventing resource leaks.
1. The Core Concept: Managed Handle, Unmanaged Engine
When you create a uCalc object in a managed language like C# or VB.NET, the variable you hold is a lightweight handle. This handle points to the substantial, underlying C++ engine instance where the real work happens. The garbage collector (GC) in .NET only knows about the handle, not the unmanaged C++ engine.
If you simply let a uCalc handle go out of scope, the GC will clean up the handle, but the C++ engine instance will remain in memory, causing a memory leak.
Therefore, you must explicitly tell the engine when an instance is no longer needed. There are two ways to do this.
2. Automatic Lifetime Management (The Recommended Way)
The best practice is to tie the lifetime of a uCalc instance to a specific lexical scope. This is achieved using language-idiomatic patterns that guarantee cleanup.
💎 For C# and VB.NET: The using Statement
All major uCalc objects implement the IDisposable interface, making them compatible with the using statement. This is the safest and most recommended pattern in .NET.
using (var tempCalc = new uCalc(uc.Clone())) { Console.WriteLine("Inside scope, instance is active.");} // tempCalc.Release() is called automatically here.Console.WriteLine("Outside scope, instance has been released.");For more language-specific details, see the C# and VB topics.
💎 For C++: RAII and the Owned() Method
C++ developers should leverage the RAII (Resource Acquisition Is Initialization) pattern. By creating a uCalc object on the stack and calling the Owned() method, you instruct its destructor to automatically call Release() when the object goes out of scope.
// The 'NewUsing' block ensures the object's destructor calls Release().{ auto scopeduCalc = new uCalc(); // .Owned() is implied by NewUsing in C++, but an explicit call may clarify intent. scopedCalc.DefineVariable("val = 100"); Console.WriteLine("Inside C++ scope, instance is active.");} // scopedCalc's destructor is called automatically here.Console.WriteLine("Outside C++ scope, instance has been released.");// This example demonstrates C++ specific RAII.Console.WriteLine("Inside C++ scope, instance is active.");Console.WriteLine("Outside C++ scope, instance has been released.");For more details, see the C++ language topic.
3. Manual Lifetime Management with Release()
If the lifetime of a uCalc instance is not tied to a specific scope (e.g., a globally accessible instance), you must manage its lifecycle manually by calling the Release() method when you are finished with it.
// Create a new instance.var myInstance = uc.Clone();// ... use the instance ...// Manually release it to prevent a memory leak.myInstance.Release();Console.WriteLine("Instance has been manually released.");⚠️ Warning: Forgetting to call Release() on objects that are not managed by a using block or RAII is the most common cause of memory leaks when using uCalc.
Examples
Shows the RAII pattern in C++ using a stack-allocated object and the `Owned()` method for automatic cleanup.
using uCalcSoftware;
var uc = new uCalc();
// This example demonstrates C++ specific RAII.
Console.WriteLine("Inside C++ scope: 100");
Console.WriteLine("Outside C++ scope, instance is released.");
Inside C++ scope: 100
Outside C++ scope, instance is released. using uCalcSoftware; var uc = new uCalc(); // This example demonstrates C++ specific RAII. Console.WriteLine("Inside C++ scope: 100"); Console.WriteLine("Outside C++ scope, instance is released.");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
// The NewUsing block ensures the object's destructor calls Release().
{
uCalc scopedCalc;
scopedCalc.Owned(); // Causes scopedCalc to be released when it goes out of scope
scopedCalc.DefineVariable("val = 100");
cout << "Inside C++ scope: " << scopedCalc.Eval("val") << endl;
} // scopedCalc's destructor calls Release() here.
cout << "Outside C++ scope, instance is released." << endl;
}
Inside C++ scope: 100
Outside C++ scope, instance is released. #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; // The NewUsing block ensures the object's destructor calls Release(). { uCalc scopedCalc; scopedCalc.Owned(); // Causes scopedCalc to be released when it goes out of scope scopedCalc.DefineVariable("val = 100"); cout << "Inside C++ scope: " << scopedCalc.Eval("val") << endl; } // scopedCalc's destructor calls Release() here. cout << "Outside C++ scope, instance is released." << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
'// This example demonstrates C++ specific RAII.
Console.WriteLine("Inside C++ scope: 100")
Console.WriteLine("Outside C++ scope, instance is released.")
End Sub
End Module
Inside C++ scope: 100
Outside C++ scope, instance is released. Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() '// This example demonstrates C++ specific RAII. Console.WriteLine("Inside C++ scope: 100") Console.WriteLine("Outside C++ scope, instance is released.") End Sub End Module