ZetCode

FreeBasic Destructor Keyword

Last modified June 5, 2026

The FreeBasic Destructor keyword defines a special member function that is automatically called when an object is destroyed. Destructors are essential for proper resource cleanup in user-defined types.

Basic Definition

In FreeBasic, a Destructor is a special method of a UDT (User Defined Type) that executes when the object goes out of scope or is explicitly deleted. Unlike C++, FreeBASIC destructors do not use a tilde prefix; they are defined with the Destructor typename() syntax.

Destructors cannot take parameters or return values. Their primary purpose is to release resources like memory, file handles, or network connections that the object may have acquired during its lifetime.

Object-oriented features such as user-defined Constructors and Destructors are only supported in the default dialect (-lang fb).

Simple Destructor Example

This example shows a basic UDT with a constructor and destructor.

simple_destructor.bas
Type Resource
    Public:
        Declare Constructor()
        Declare Destructor()
    Private:
        id As Integer
End Type

Constructor Resource()
    Print "Resource acquired"
    id = 42
End Constructor

Destructor Resource()
    Print "Resource released for id "; id
End Destructor

Scope
    Dim res As Resource
End Scope

Print "After scope"

Here we define a Resource type with constructor and destructor. When the object is created, the constructor runs. When it goes out of scope, the destructor automatically executes. This ensures proper cleanup.

Destructor with Dynamic Memory

Destructors are particularly useful for managing dynamically allocated memory.

dynamic_memory.bas
Type Buffer
    Public:
        Declare Constructor(size As Integer)
        Declare Destructor()
        Declare Property Data() As Byte Ptr
    Private:
        buffer As Byte Ptr
        bufSize As Integer
End Type

Constructor Buffer(size As Integer)
    buffer = Allocate(size)
    bufSize = size
    Print "Allocated "; size; " bytes"
End Constructor

Destructor Buffer()
    If buffer Then
        Deallocate(buffer)
        Print "Freed "; bufSize; " bytes"
    End If
End Destructor

Property Buffer.Data() As Byte Ptr
    Return buffer
End Property

Scope
    Dim buf As Buffer = Buffer(1024)
    ' Use the buffer...
End Scope

This Buffer type manages dynamic memory allocation. The constructor allocates memory, while the destructor ensures it is freed when the object leaves scope. This prevents memory leaks if the programmer forgets to deallocate manually.

Destructor in Array of Objects

Destructors are automatically called for each element when an array of objects is destroyed.

array_destructor.bas
Type Item
    Public:
        Declare Constructor()             ' required when declaring fixed-size arrays
        Declare Constructor(index As Integer)
        Declare Destructor()
    Private:
        itemIndex As Integer
End Type

Constructor Item()
    itemIndex = 0
    Print "Item default created"
End Constructor

Constructor Item(index As Integer)
    itemIndex = index
    Print "Item "; index; " created"
End Constructor

Destructor Item()
    Print "Item "; itemIndex; " destroyed"
End Destructor

Scope
    Dim items(1 To 5) As Item
    For i As Integer = 1 To 5
        items(i) = Item(i)
    Next
End Scope

In FreeBasic, when any constructor is declared for a UDT, a matching default (parameterless) constructor must also be provided in order to declare fixed-size arrays of that type. When the array items goes out of scope, destructors are called for elements in reverse order of construction. The assignments in the loop also destroy temporaries immediately.

Destructor with Inheritance

Destructors are called in reverse order of construction in an inheritance hierarchy. For the base class destructor to be invoked correctly through a base-class pointer (polymorphic destruction), the destructor in the base type must be declared Virtual and the derived type must Extends Object.

inheritance_destructor.bas
Type MyBase Extends Object
    Public:
        Declare Constructor()
        Declare Virtual Destructor()
End Type

Constructor MyBase()
    Print "Base constructor"
End Constructor

Destructor MyBase()
    Print "Base destructor"
End Destructor

Type MyDerived Extends MyBase
    Public:
        Declare Constructor()
        Declare Destructor() Override
End Type

Constructor MyDerived()
    Print "Derived constructor"
End Constructor

Destructor MyDerived()
    Print "Derived destructor"
End Destructor

Scope
    Dim obj As MyDerived
End Scope

For a plain stack object, the derived destructor still runs before the base destructor even without Virtual (static type). Declare the base destructor Virtual to ensure the correct destructor is called when an object is deleted through a base-class pointer.

Manual Destruction with Delete

Destructors can be explicitly called using the Delete operator for dynamically allocated objects.

manual_destructor.bas
Type ManagedResource
    Public:
        Declare Constructor()
        Declare Destructor()
    Private:
        id As Integer
End Type

Constructor ManagedResource()
    id = 1
    Print "Resource created"
End Constructor

Destructor ManagedResource()
    Print "Resource destroyed"
End Destructor

Dim res As ManagedResource Ptr = New ManagedResource
' Use the resource...
Delete res
Print "After deletion"

Here we manually control the object's lifetime. The New operator creates the object, and Delete explicitly calls the destructor. This is useful for objects with dynamic storage duration.

Destructor and Runtime Errors

When a runtime error is raised using the Error statement, execution jumps to an error handler established with On Error Goto (if any). Local objects' destructors execute as their stack frames unwind during error recovery, but FreeBASIC does not provide .NET/Java-style structured exception handling with Try/Catch blocks.

runtime_error.bas
Type SafeResource
    Public:
        Declare Constructor()
        Declare Destructor()
    Private:
        n As Integer
End Type

Constructor SafeResource()
    n = 42
    Print "SafeResource #"; n; " created"
End Constructor

Destructor SafeResource()
    Print "SafeResource #"; n; " destroyed"
End Destructor

Sub RiskyOperation()
    Dim res As SafeResource
    Print "About to raise runtime error"
    Error 999
    Print "This line is not reached"
End Sub

On Error Goto handler
RiskyOperation()
Print "No error path"
End

handler:
Print "In error handler, Err = "; Err

Note that when a runtime error is raised with Error, the local object's destructor is not guaranteed to run before the On Error Goto handler takes control — the stack frame may not be fully unwound. Additionally, Err is typically zero inside the handler because the runtime clears the error status once control transfers. FreeBASIC does not perform C++-style RAII stack unwinding on runtime errors. Rely on destructors only for normal scope exits and Delete, not as a safety net for Error-based control flow.

Destructor with File Handling

Destructors can ensure files are properly closed even if errors occur.

file_destructor.bas
Type FileWrapper
    Public:
        Declare Constructor(fileName As String)
        Declare Destructor()
        Declare Function ReadLine() As String
    Private:
        fileNum As Integer
End Type

Constructor FileWrapper(fileName As String)
    fileNum = FreeFile()
    If Open(fileName For Input As #fileNum) Then
        Print "Failed to open file"
        fileNum = 0
    Else
        Print "File opened successfully"
    End If
End Constructor

Destructor FileWrapper()
    If fileNum Then
        Close #fileNum
        Print "File closed"
    End If
End Destructor

Function FileWrapper.ReadLine() As String
    Dim Result As String
    If fileNum = 0 Then Return ""
    Line Input #fileNum, Result
    Return Result
End Function

Scope
    Dim file As FileWrapper = FileWrapper("test.txt")
    Print "First line: "; file.ReadLine()
End Scope

The FileWrapper type manages file resources safely using RAII. The constructor opens the file, and the destructor ensures it is closed when the wrapper leaves scope. This pattern avoids resource leaks even when execution exits via Return or an early exit from a scope block.

Best Practices

This tutorial covered the FreeBasic Destructor keyword with practical examples showing its usage for proper resource management and cleanup.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all FreeBasic Tutorials.