


Managing the life cycle of C pointers in Golang: starting with GC recycling
Oct 12, 2025 am 03:42 AMThis article aims to explore how to effectively manage the life cycle of C pointers when interacting with C libraries in Golang, especially when Golang's garbage collector (GC) recycles structures containing C pointers. We will discuss methods of copying C structures into Go-managed memory, creating explicit release methods, and utilizing finalizers, emphasizing that best practice is to combine explicit release methods with finalizers to ensure that resources are reliably released.
In Golang, when you need to interact with the C library, you often encounter situations where you need to store pointers to C structures in Go structures. For example:
/* #include <stdlib.h> typedef struct { int value; } b; */ import "C" type A struct { s*Cb }</stdlib.h>
When a structure of type A is recycled by the garbage collector, the memory pointed to by its internal C pointer s may not be released, resulting in a memory leak. Therefore, we need to find a way to ensure that the C memory pointed to by the s pointer can be released correctly before the GC reclaims the A structure.
1. Copy the C structure to the memory managed by Go
If the C struct is not particularly complex and is not shared with C code, then the safest approach is to copy the contents of the C struct into Go-managed memory. In this way, Go's GC can automatically manage this part of memory without manually releasing it.
/* #include <stdlib.h> typedef struct { int value; } b; */ import "C" type A struct { s Cb // Directly store C structure} func example() { // Assume that cStruct is a variable of type Cb cStruct := Cb{value: 10} a := A{s: cStruct} // now as is a copy of the C structure, managed by Go GC_ = a }</stdlib.h>
The advantage of this method is that it is simple and safe, and completely relies on Go's GC mechanism. However, it does not work in the following cases:
- C structures are too complex and copying overhead is too high.
- C structures are shared with C code and cannot be copied at will.
2. Create an explicit Free() method
For cases where the C structure cannot be copied, a common approach is to create a Free() or Close() method for the Go structure containing the C pointer and manually release the memory pointed to by the C pointer in the method.
/* #include <stdlib.h> typedef struct { int value; } b; void free_b(void *ptr) { free(ptr); } */ import "C" import "unsafe" type A struct { s*Cb } func (a *A) Free() { if as != nil { C.free_b(unsafe.Pointer(as)) as = nil // avoid double free } } func example() { a := A{s: (*Cb)(C.malloc(C.sizeof_b))} // ... use as ... a.Free() // Explicitly release memory}</stdlib.h>
Things to note:
- The Free() method should be safe to call multiple times, that is, after releasing the memory, the pointer is set to nil to avoid program crashes caused by repeated releases.
- The user must be clearly informed that after using the structure, the Free() method must be called.
3. Use runtime.SetFinalizer
Golang provides the runtime.SetFinalizer function, which can execute a cleanup function before the object is recycled by GC. We can use this to free the C pointer.
/* #include <stdlib.h> typedef struct { int value; } b; void free_b(void *ptr) { free(ptr); } */ import "C" import "runtime" import "unsafe" type A struct { s*Cb } func (a *A) free() { if as != nil { C.free_b(unsafe.Pointer(as)) as = nil } } func NewA() *A { a := &A{s: (*Cb)(C.malloc(C.sizeof_b))} runtime.SetFinalizer(a, (*A).free) return a } func example() { a := NewA() // ... use as ... // There is no need to explicitly call Free(), GC will automatically call free() _ = a }</stdlib.h>
Things to note:
- runtime.SetFinalizer is not guaranteed to be executed because the execution timing of GC is uncertain.
- If garbage is generated too fast, garbage collection may not be able to keep up, causing the finalizer to be delayed or even not executed.
- Runtime.SetFinalizer should be used as a complement to the Free() method, not as a replacement.
best practices
Best practice is to use the explicit Free() method with runtime.SetFinalizer:
- Provide a Free() method for users to explicitly release resources.
- Use runtime.SetFinalizer to register the finalizer as a final safeguard to prevent users from forgetting to call the Free() method.
This can ensure to the greatest extent that the memory pointed to by the C pointer can be released correctly and avoid memory leaks.
Summarize
Managing the life cycle of C pointers in Golang is a complex problem, and you need to choose an appropriate solution based on the actual situation. Copying a C structure to Go-managed memory is the safest way, but only suitable for certain scenarios. The explicit Free() method combined with runtime.SetFinalizer is a more general solution that can effectively avoid memory leaks. Be sure to carefully consider the pros and cons of each option and choose the method that best suits your scenario.
The above is the detailed content of Managing the life cycle of C pointers in Golang: starting with GC recycling. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

ArtGPT
AI image generator for creative art from text prompts.

Stock Market GPT
AI powered investment research for smarter decisions

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Goprovidessimpleandefficientfilehandlingusingtheosandbufiopackages.Toreadasmallfileentirely,useos.ReadFile,whichloadsthecontentintomemorysafelyandautomaticallymanagesfileoperations.Forlargefilesorincrementalprocessing,bufio.Scannerallowsline-by-liner

struct{} is a fieldless structure in Go, which occupies zero bytes and is often used in scenarios where data is not required. It is used as a signal in the channel, such as goroutine synchronization; 2. Used as a collection of value types of maps to achieve key existence checks in efficient memory; 3. Definable stateless method receivers, suitable for dependency injection or organization functions. This type is widely used to express control flow and clear intentions.

GracefulshutdownsinGoapplicationsareessentialforreliability,achievedbyinterceptingOSsignalslikeSIGINTandSIGTERMusingtheos/signalpackagetoinitiateshutdownprocedures,thenstoppingHTTPserversgracefullywithhttp.Server’sShutdown()methodtoallowactiverequest

Use the encoding/json package of the standard library to read the JSON configuration file; 2. Use the gopkg.in/yaml.v3 library to read the YAML format configuration; 3. Use the os.Getenv or godotenv library to overwrite the file configuration; 4. Use the Viper library to support advanced functions such as multi-format configuration, environment variables, automatic reloading; it is necessary to define the structure to ensure type safety, properly handle file and parsing errors, correctly use the structure tag mapping fields, avoid hard-coded paths, and recommend using environment variables or safe configuration storage in the production environment. It can start with simple JSON and migrate to Viper when the requirements are complex.

CGOenablesGotocallCcode,allowingintegrationwithClibrarieslikeOpenSSL,accesstolow-levelsystemAPIs,andperformanceoptimization;itrequiresimporting"C"withCheadersincomments,usesC.function()syntax,anddemandscarefulmemorymanagement.However,CGOinc

Install the sqlcCLI tool, it is recommended to use curl scripts or Homebrew; 2. Create a project structure, including db/schema.sql (table structure), db/query.sql (annotated query) and sqlc.yaml configuration files; 3. Define database tables in schema.sql; 4. Write SQL queries with --name:annotation and :exec/:one/:many directives in query.sqlc.yaml; 5. Configure sqlc.yaml to specify package paths, query files, schema files, database engines and generation options; 6. Run sqlcgenerate to generate type-safe Go code, including models, query methods and interfaces

This article aims to resolve the "undefined" error encountered in Go when trying to use strconv.Itoa64 for integer-to-string conversion. We will explain why Itoa64 does not exist and give details on the correct alternative to strconv.FormatInt in the strconv package. Through instance code, readers will learn how to efficiently and accurately convert integer types into string representations in specified partitions, avoid common programming traps and improve code robustness and readability.

Implements JSON serialization and deserialization of customizable Go structures for MarshalJSON and UnmarshalJSON, suitable for handling non-standard formats or compatible with old data. 2. Control the output structure through MarshalJSON, such as converting field formats; 3. Parsing special format data through UnmarshalJSON, such as custom dates; 4. Pay attention to avoid infinite loops caused by recursive calls, and use type alias to bypass custom methods.
