4 ms·
I agree with everything you write, but the opposition to "too much cgo" has another reason too: what's the point of using a memory safe language if you tie it t
by rob74 5y ago
I agree with everything you write, but the opposition to "too much cgo" has another reason too: what's the point of using a memory safe language if you tie it to a large body of code that is not memory safe? Rust applications using C libraries have this issue too, although the performance penalty of calling C from Rust is less than for Go.
Of course, there are still valid reasons for using cgo. But if you are building a library, you should ask yourself the "cgo or not cgo" question even more seriously, because you will be forcing everybody who uses your library to use cgo too...
- srer 5y agoIs it memory safe? As I understood it you lose that as soon as you start using the namesake keyword, "go".
- matthewmacleod 5y agoYes – Go is generally memory safe, with the exception of the `unsafe` package which is (obviously) not. Outside of this, there is no access to raw pointers or pointer arithmetic. The use of goroutines does not affect memory safety. None of this means that you can't make an absolute mess of concurrency, but that's not a memory safety concern.
- srer 5y agohttps://research.swtch.com/gorace https://research.swtch.com/gorace describes a loss of memory safety through data races, but I note it says "In the current Go implementations" and was written in 2010. I never heard of news that the situation had changed, but if it has I'm most interested in when it did! :)
- jrockway 5y agoIt really depends on where you draw the line. This is an obviously-incorrect program (`++` isn't atomic): func main() { var x, y int64 doneCh := make(chan struct{}) inc := func() { for i := 0; i < 2<<20; i++ { x++ // line 13 in test/main.go atomic.AddInt64(&y, 1) } doneCh <- struct{}{} return } go inc() go inc() <-doneCh <-doneCh fmt.Printf("x, y = %v, %v\n", x, y) } This prints something like: $ go run main.go x, y = 3482626, 4194304 If you run it with the race detector the problem is clear: $ go run -race main.go ================== WARNING: DATA RACE Read at 0x00c0001bc008 by goroutine 7: main.main.func1() /home/jrockway/test/main.go:13 +0x50 Previous write at 0x00c0001bc008 by goroutine 8: main.main.func1() /home/jrockway/test/main.go:13 +0x64 Goroutine 7 (running) created at: main.main() /home/jrockway/test/main.go:19 +0x176 Goroutine 8 (running) created at: main.main() /home/jrockway/test/main.go:20 +0x184 ================== x, y = 4189962, 4194304 Found 1 data race(s) exit status 66 This is not strictly a memory safety problem (this can't crash the runtime), but a program that returns the wrong answer is pretty useless, so there is that. Obviously if x were going to be used as a pointer through the `unsafe` package, you could have problems. (Though I think that x will always be less than y, so if you have proved that memory[base+y] is safe to read, then memory[base+x] is safe to read. But it's easy to imagine a scenario where you overcount instead of undercount.
- samhw 5y agoI'm very confused by this comment. Memory safety doesn't mean "can't crash the runtime"[0]. That would exclude the most basic, canonical examples of memory unsafety: use after free, buffer overwrite/overread, double free, race conditions, etc. The erroneous Go exemplar you posted is literally one of the first examples of memory unsafety on Wikipedia: https://en.wikipedia.org/wiki/Memory_safety https://en.wikipedia.org/wiki/Memory_safety. Go is not memory safe by any stretch of the imagination. It doesn't even claim to be. At most it incidentally prevents a narrow subset of unsafe memory uses, compared with C (not a high standard), in the sense of providing an array type (and concomitant string type) rather than just pointer arithmetic.
- tedunangst 5y agoWriting to a slice concurrently can split the data pointer and capacity, and now you have a pointer that can be accessed out of bounds.
- _ph_ 5y agoYes, memory safety certainly would be an argument for rewriting a library in Go. But we are talking here about an extremely well tested and robust C program which is actively maintained. In most cases, it is more likely to have correct programs by calling the C version than attempting a port, which can introduced bugs of its own.
- rob74 5y agoYes, in this particular case, SQLite has a stellar reputation for stability, test coverage etc. But for other C codebases, even if they have been around for a long time and are stable and well maintained, exploits have still been found...