On Sun, Nov 9, 2014 at 12:53 PM, <
nicolas...@gmail.com> wrote:
>
> Question 1)
> ===========
> Let's have these two pieces of code:
>
> var x [10]byte
> C.f(&x[0]) // f modifies the bytes in x
>
> or
>
> var x C.T // in C file: typedef struct T {unsigned char data[10];}
> T;
> C.f(&x) // f modifies the bytes in x
>
> I understand that with a future moving GC, if GC runs when f() is running,
> f() will corrupt heap.
> But is dvyukov saying that the code above is already broken now with Go 1.3,
> even if C code doesn't change any pointer in the object but just plain bytes
> ?
This kind of code will work in Go 1.4. You are correct that the kind
of problem Dmitriy is discussing only arises if the C code changes a
pointer value. In 1.3 and 1.4 there is no issue with a *byte.
In future Go releases there will be a problem, because we want to
leave open the possibility of a moving GC, in which case this kind of
code will stop working. I think it will be possible to have cgo
detect and reject some obvious cases. It may also be possible in some
cases to have cgo automatically copy the memory into a safe area
before passing it to the C code. I'm not sure think that can work in
general, though.
> In
http://golang.org/cmd/cgo/, I read:
> "In Go, you must pass the pointer to the first element explicitly:
> C.f(&x[0])."
> If this idiom may not be supported in the future, shouldn't a warning be
> already included in this documentation ?
I'll send a CL to fix that case.
We haven't written down rules in the docs because we haven't settled
what the rules are. These are issues 8839 and 8310.
> Question 2)
> ===========
>
>> #15 r... says:
>> Passing a Go heap pointer to C can break today's 1.3 GC which does not
>> scan C stacks / variables.
>
> If passing pointers &x[0] is already a problem in Go 1.3, I will change all
> my code right now.
> But I don't understand this stack/variables issue. Can someone explain this
> point ?
It will break if you don't keep a pointer in Go code. If you are
careful to ensure that Go code holds a copy of the pointer, you will
be OK with 1.3 and 1.4.
> Question 3)
> ===========
>
> If passing &x[0] is not recommended, the only official means to communicate
> between Go world and C heap is to use:
> func C.CString(string) *C.char
> func C.GoString(*C.char) string
> func C.GoStringN(*C.char, C.int) string
> func C.GoBytes(unsafe.Pointer, C.int) []byte
>
> or wrapping C array in struct, so that they can be passed by value between
> Go and C, like this ?
>
>
http://play.golang.org/p/5ck0C_NKVx
>
> I noticed that because a pointer is passed, the object always escape to
> heap. So, a copy is better for performance than creating garbage on heap, in
> the end.
Simply using a struct does not help. In your code the pointer to the
struct is still a Go pointer. Using a struct would only help if you
called into C to get memory to write into. That is an addition to
your list above: call a C function that calls malloc and returns a C
pointer. You still can't store a Go pointer into that C pointer, but
you can safely store any non-pointer values.
Ian