Skip to content

fix: free model backend, buffer and context when the model is dropped - #23

Merged
PABannier merged 1 commit into
mainfrom
cleanup/fix-model-leak
Sep 16, 2026
Merged

PABannier merged 1 commit into
mainfrom
cleanup/fix-model-leak

Conversation

@PABannier

Copy link
Copy Markdown
Owner

Bug

sam3_load_model returns std::make_shared<sam3_model>(), and sam3_model has no destructor. Nothing in the library or examples calls sam3_free_model, so dropping the last shared_ptr leaked the weight buffer, the ggml context and the backend. The loader's early return nullptr paths (after the backend/buffer were created) leaked the same way.

Fix

Construct the shared_ptr with a deleter that calls sam3_free_model and then deletes the model. sam3_free_model nulls every pointer it frees, so a caller that already freed the model manually is unaffected.

Lifetimes are safe: every example declares model before state/tracker, so their buffers are released before the backend.

Verification

A throwaway program loads sam2.1_hiera_tiny_q8_0 plus a state 5 times, drops them each time, and prints resident memory:

iter CPU before CPU after Metal before Metal after
0 55.0 MB 12.7 MB 86.1 MB 44.3 MB
1 97.5 12.9 128.4 44.4
2 139.8 12.9 170.7 45.3
3 182.1 13.8 213.0 45.3
4 224.4 14.1 255.4 45.3

Output is also unchanged: a parity tool runs encode, PVS point + box, and a 3-frame visual track, then compares the output byte for byte with origin/main:

PARITY OK   edgetam_f16 gpu0
PARITY OK   edgetam_f16 gpu1
PARITY OK   sam2.1_hiera_tiny_q8_0 gpu0
PARITY OK   sam2.1_hiera_tiny_q8_0 gpu1

A failing load (missing file) still returns nullptr cleanly.

🤖 Generated with Claude Code

https://claude.ai/code/session_01M2qLmQ9ag49hT61V6i9qAq

sam3_load_model returned std::make_shared<sam3_model>(), and sam3_model
has no destructor. Nothing ever called sam3_free_model, so each loaded
model leaked its weight buffer, ggml context and backend (~42 MB per
load for SAM2.1-tiny q8_0, on CPU and Metal). It also leaked on every
early-return failure path inside the loader.

Give the shared_ptr a deleter that calls sam3_free_model. The function
nulls what it frees, so an explicit call before release stays safe.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M2qLmQ9ag49hT61V6i9qAq
@PABannier
PABannier merged commit 8f806c1 into main Sep 16, 2026
3 checks passed
@PABannier
PABannier deleted the cleanup/fix-model-leak branch September 16, 2026 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant