Standard_ProgramError in Open CASCADE

Diagnostic signature

Standard_ProgramError

A core OCCT exception raised when a critical programmatic invariant is violated, most commonly by attempting to create an intrusive handle to a stack-allocated transient object.

What it means

`Standard_ProgramError` is a foundational exception class within the Open CASCADE Technology (OCCT) framework. Inheriting from `Standard_Failure`, it serves as a primary diagnostic mechanism to signal that a fundamental API contract or runtime invariant has been breached. When this exception is thrown, it indicates a critical logic flaw—such as an invalid topological state, a broken algorithmic assumption, or improper memory usage—that prevents the geometry kernel from safely executing the requested operation. The diagnostic forces execution to halt rather than risking undefined behavior, memory corruption, or silent geometry generation errors.

Why it happens

The most frequent developer-induced trigger for this diagnostic stems from improper lifecycle management of OCCT transient objects. OCCT relies on intrusive reference counting via the `opencascade::handle` mechanism for any class derived from `Standard_Transient`. If a transient object (like a geometry surface or topological node) is allocated on the stack, its internal reference count initializes to zero. If the application subsequently attempts to acquire a managed handle to this object—often by implicitly or explicitly invoking its `This()` method—OCCT detects the zero reference count. To prevent inevitable segmentation faults caused by a handle attempting to free stack memory upon destruction, `Standard_Transient::This()` proactively raises `Standard_ProgramError`. Beyond memory management, the diagnostic is also explicitly raised by internal framework components via assertion macros (such as `Standard_ProgramError_Raise_if` and `Standard_ASSERT_RAISE`) when local geometric routines detect impossible states, such as out-of-bounds indices or null references in data structures.

Minimal reproduction

#include <Standard_Transient.hxx>
#include <Geom_CartesianPoint.hxx>
#include <gp_Pnt.hxx>
#include <iostream>

int main() {
    try {
        // ERROR: Allocating a Standard_Transient-derived object on the stack.
        // Its internal reference count is initialized to 0.
        Geom_CartesianPoint myStackPoint(gp_Pnt(0.0, 0.0, 0.0));
        
        // Attempting to create an OCCT handle from an unmanaged stack object.
        // Calling This() checks the reference count, sees 0, and throws Standard_ProgramError.
        opencascade::handle<Standard_Transient> h = myStackPoint.This();
    } catch (const Standard_ProgramError& e) {
        std::cerr << "Caught exception: " << e.GetMessageString() << std::endl;
        return 1;
    }
    return 0;
}

How to fix it

Allocate Standard_Transient objects on the heap using new, allowing OCCT's handle mechanism to properly track and manage reference counts.

```C++
#include <Standard_Transient.hxx>
#include <Geom_CartesianPoint.hxx>
#include <gp_Pnt.hxx>
#include <iostream>

int main() {
    try {
        // CORRECT: Allocate the transient object on the heap and assign directly to a handle.
        // The constructor of the handle safely increments the reference count.
        opencascade::handle<Geom_CartesianPoint> myHeapPoint = new Geom_CartesianPoint(gp_Pnt(0.0, 0.0, 0.0));
        
        // The handle now manages the object securely. This() successfully returns the pointer.
        opencascade::handle<Standard_Transient> h = myHeapPoint->This();
    } catch (const Standard_ProgramError& e) {
        std::cerr << "Caught exception: " << e.GetMessageString() << std::endl;
        return 1;
    }
    return 0;
}
```

Step 1

Step 2

Step 3

Step 4

Upstream references

Open CASCADE Technology OCCT 7.8.0 — Standard_ProgramError.hxx — retrieved 2026-08-11

Standard_Transient.hxx Source (OCCT 7.8.0)