2017-02-27 1 views
3

Ich bin ein relativer Neuling zu gehen. Ich habe viel mit CGO gearbeitet und eine Schnittstelle zu einem CAPI aufgebaut. Der CAPI verwendet einen registrierten Rückruf und einen void* Cookie-Parameter für den Rückruf.Ändern Zeiger in Go aufgrund von Garbage Collection den Wert?

Hier ist ein Code beispielhaft mein Problem:

/* 
void cb(void *cookie) { 
    callGo(cookie); 
} 

go_register_cb(void *ptr) { 
    register_cb(&cb, ptr); 
} 
*/ 
import "C" 

und

import "C" 

//export callGo 
callGo(ptr unsafe.Pointer) { 
    x := (*MyStruct)(ptr) 
    x.doSomething() 
} 

func (x *MyStruct) Start() { 
    C.go_register_cb(unsafe.Pointer(x)) 
} 

Dieser Code verursacht einen Laufzeitfehler zu Go Zeiger Zeiger zu gehen.

Ich glaube, ich verstehe die grundlegenden Auswirkungen der Go-Zeiger in C-Land, die C-Land-Referenz wird nicht in der Garbage Collector berücksichtigt werden, so dass C am Ende mit einer veralteten Referenz.

Die spezifische Anforderung, dass ich einen Go-Zeiger nicht an eine Datenstruktur übergeben kann, die selbst einen Go-Zeiger enthält, ist verwirrender. Das einzige, was für mich Sinn macht, ist, dass Zeiger in Go den Wert (d. H. Die Adresse, auf die sie verweisen) aufgrund der Speicherbereinigung ändern. Ist das der Fall?

Antwort

2

Diese Regeln zum Übergeben des Zeigers zwischen Go-Code und C-Code werden zur Laufzeit dynamisch überprüft. Also, wenn Sie sie brechen, tritt der Fehler auf.

Und Ihre Vermutung ist richtig. Adressen dürfen sich aufgrund von Garbage Collection ändern (Pointer werden aktualisiert).

Hinweis here from golang.org:

Selbst wenn ein UIntPtr die Adresse eines Objekts hält, wird der Müll Sammler nicht, dass UIntPtr Wert aktualisieren, wenn sich das Objekt bewegt, noch wird das UIntPtr von dem Objekt halten zurückgefordert .

So ist ein Verschieben von Objekten aufgrund von GC möglich.