Skip to content

Memory leak: CString not freed in helpers.go valToBuffer() (hot path) #621

@e-gineer

Description

@e-gineer

Description

The valToBuffer() function in helpers.go creates a C.CString allocation that is never freed, causing a significant memory leak. This is a hot path function called for every string column in every row returned by queries.

Current Code

func valToBuffer(val interface{}, oid C.Oid, buffer C.StringInfo) (err error) {
    // ...
    C.fdw_appendBinaryStringInfo(buffer, C.CString(valueString), C.int(len(valueString)))
    return
}

Problem

C.CString() allocates memory on the C heap which must be explicitly freed with C.free(). The current code passes the result directly to fdw_appendBinaryStringInfo without storing it, making it impossible to free.

Impact

  • Severity: High - This is a hot path
  • Frequency: Called for every string column in every row
  • Memory leaked: Length of each string value + overhead
  • Example: Query returning 10,000 rows × 10 string columns = 100,000 leaks per query

Proposed Fix

Store CString result and free immediately after use:

cValueString := C.CString(valueString)
C.fdw_appendBinaryStringInfo(buffer, cValueString, C.int(len(valueString)))
C.free(unsafe.Pointer(cValueString))

Important: Use explicit C.free() instead of defer because:

  1. This is a hot path called thousands/millions of times per query
  2. defer adds ~50-100ns overhead per call plus heap allocation
  3. The immediate free pattern is already used elsewhere in the codebase (see errors.go)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions