Garbage collection in cgo - memory-management

I have the following code in Go which uses cgo:
func foo() {
bar := new(C.struct_bar)
...
}
Will bar be garbage collected after the function finishes its execution or I need to explicitly call free?

Yes, even though the struct_bar is a C type, the memory is allocated by Go, and will be collected by Go.
Any memory allocated in C however is not tracked by the Go GC. The C code should manage this on it's own, but in cases like C.CString where Go triggers the allocation, you must manually free the memory with C.free.

Related

Why finalizer is never called?

var p = &sync.Pool{
New: func() interface{} {
return &serveconn{}
},
}
func newServeConn() *serveconn {
sc := p.Get().(*serveconn)
runtime.SetFinalizer(sc, (*serveconn).finalize)
fmt.Println(sc, "SetFinalizer")
return sc
}
func (sc *serveconn) finalize() {
fmt.Println(sc, "finalize")
*sc = serveconn{}
runtime.SetFinalizer(sc, nil)
p.Put(sc)
}
The above code tries to reuse object by SetFinalizer, but after debug I found finalizer is never called, why?
UPDATE
This may be related:https://github.com/golang/go/issues/2368
The above code tries to reuse object by SetFinalizer, but after debug I found finalizer is never called, why?
The finalizer is only called on an object when the GC
marks it as unused and then tries to sweep (free) at the end
of the GC cycle.
As a corollary, if a GC cycle is never performed during the runtime of your program, the finalizers you set may never be called.
Just in case you might hold a wrong assumption about the Go's GC, it may worth noting that Go does not employ reference counting on values; instead, it uses GC which works in parallel with the program, and the sessions during which it works happen periodically and are triggered by certain parameters like pressure on the heap produced by allocations.
A couple assorted notes regarding finalizers:
When the program terminates, no GC is forcibly run.
A corollary of this is that a finalizer is not guaranteed
to run at all.
If the GC finds a finalizer on an object about to be freed,
it calls the finalizer but does not free the object.
The object itself will be freed only at the next GC cycle —
wasting the memory.
All in all, you appear as trying to implement destructors.
Please don't: make your objects implement the sort-of standard method called Close and state in the contract of your type that the programmer is required to call it when they're done with the object.
When a programmer wants to call such a method no matter what, they use defer.
Note that this approach works perfectly for all types in the Go
stdlib which wrap resources provided by the OS—file and socket descriptors. So there is no need to pretend your types are somehow different.
Another useful thing to keep in mind is that Go was explicitly engineered to be no-nonsense, no-frills, no-magic, in-your-face language, and you're just trying to add magic to it.
Please don't, those who like decyphering layers of magic do program in Scala different languages.

can memory for a golang variable be used outside its declaration scope

I am trying to understand memory management in go. can i safely use the memory allocated inside a scope.
type BigConfigurationData struct {
subject1config *Subject1Config
subject2config *Subject2Config
...
}
var p BigConfigurationData
if aFlag {
var subject1config = Subject1Config {
foo: bar
}
p.subject1config = &subject1config
}
// can i use p.subject1config here and expect the memory has not been cleaned up?
Go looks simple, but in fact it does a lot to help the programmer.
In Go all variables are effectively references. The compiler tracks if any memory "escapes" a scope, and then automatically allocates is on the heap (shared memory pool). If the memory does not escape the scope, compiler allocates it on the stack which is much faster.
In your case, when you assign the p.subject1config = &subject1config, this tells the compiler that the value or the memory will leave the scope. Compiler will allocte the memory from heap and thus via the reference p.subject1config you can access the memory in the outer scope.
Go garbage collector regularly checks if the memory blocks still have any refences pointing to it, and frees up the memory when no references remain.
In short, you are confusing "variable" and "memory", probably because Go automatically manages memory for you.
EDIT: This answer might be too simplisic. Please read comments below for more info. See these links for more information:
http://www.tapirgames.com/blog/golang-memory-management
https://dougrichardson.org/2016/01/23/go-memory-allocations.html

Do I have to free structs created with Cgo?

I create C structs in my Go code, like this:
var data C.MyStruct_t
Do I have to free them manually at some point, like I do when I use CString? With CString I often do something like:
ctitle := C.String(title)
defer C.free(unsafe.Pointer(&ctitle))
C.my_func(&ctitle)
No. You only call free on something that was allocated via the C *alloc functions. The C.CString and C.CBytes functions are documented as doing so internally, and requiring the use of C.free.
In this case even though data is of type C.MyStruct_t it is allocated in Go, and therefor will be handled by the Go garbage collector.

What happens to stack/heap allocated types when a runtime panic occurs?

What happens to the types that are allocated on the heap or stack before a panic occurs? Is a destructor called so that the types are deallocated? Do they linger around in the memory waiting to be overwritten by some other process? Or is it something else entirely?
I've no idea since I'm new to Rust and systems programming in general.
By default, the stack will be unwound and destructors are run. You can prove this for yourself:
struct Noisy;
impl Drop for Noisy {
fn drop(&mut self) {
println!("Dropping!");
}
}
fn main() {
let _on_stack = Noisy;
let _on_heap = Box::new(Noisy);
panic!("Oh no!");
}
This will print:
Dropping!
Dropping!
Note that there's no real difference in stack or heap here. Any heap-allocated item is going to have something on the stack pointing to it. When the handle on the stack goes out of scope, it cleans up the heap resources.
The stack is unwound until it exits from the current thread (if it's the main thread, the program exits). It's also possible to use catch_unwind. Beware using this though:
It is not recommended to use this function for a general try/catch mechanism. [...] Note that this function may not catch all panics in Rust.
Note that I said by default. You can also compile with an option whereby panics translate directly into aborting the process. At that point, the process is over and no more destructors will be run.
If you panic in a destructor, then it's also game over: the process will be aborted.

Free C pointer when collected by GC

I have a package that interfaces with a C library. Now I need to store a pointer to a C struct in the Go struct
type A struct {
s *C.struct_b
}
Obviously this pointer needs to be freed before the struct is collected by the GC. How can I accomplish that?
The best thing to do is when possible copy the C struct into go controlled memory.
var ns C.struct_b
ns = *A.s
A.s = &ns
Obviously, that won't work in all cases. C.struct_b may be too complicated or shared with something still in C code. In this case, you need to create a .Free() or .Close() method (whichever makes more sense) and document that the user of your struct must call it. In Go, a Free method should always be safe to call. For example, after free is run, be sure to set A.s = nil so that if the user calls Free twice, the program does not crash.
There is also a way to create finalizers. See another answer I wrote here. However, they may not always run and if garbage is created fast enough, it is very possible that the creation of garbage will out pace collection. This should be considered as a supplement to having a Free/Close method and not a replacement.

Resources