Earlier quoted context omitted.
You still think in C limits of possibilities. Rust could just return Option as a result for [x] syntax.
And then people would simply call .unwrap() on the return of the [] operator, leading to the same situation. It's extremely common for an array dereference to always be within the bounds, by code construction (I'm iterating over the indexes of the array, or I have an index into the array saved inside some other structure, and so on). The programmer knows it will never be out of bounds. The assert!() within the [] ope…
Getting Past C
481–490 of 504 posts
Re: Getting Past C
#482Earlier quoted context omitted.
> What do you mean by that ? Are you saying the standard decided to make it non-destructive moves ? You can still access a value after it has been moved out. use-after-move is allowed by the compiler. It places (stdlib) types in an unspecified but valid state (I've seen C++ code reusing these types and assuming that the state after move is something in particular -- it's not). Most optimizations you can do by reusing…
> Most optimizations you can do by reusing a moved value could be done automatically by the compiler Not if constructing the object is costly. It is very well possible for an object not to have a default constructor.
Re: Getting Past C
#483Earlier quoted context omitted.
> there's nothing stopping the compiler from optimizing the GC out. I don't know of a single language that comes with a GC that does this, do you? > He was comparing against what you'd get if you dropped down to ye olde C or Assembly and wrote the same algorithm there, without redundant work or waste. Right. I agree with this. But basically, we are arguing over an extremely fine semantic, which is "should you even wa…
> I don't know of a single language that comes with a GC that does this, do you? Java, .NET, Go, ML and Lisp compilers. Escape analysis allows to do that, even if just in certain special cases. Plus the more one uses value types and less heap, the GC needs to work less, specially if we take languages like Modula-3 into this mix.
Re: Getting Past C
#484Earlier quoted context omitted.
> What do you mean by that ? Are you saying the standard decided to make it non-destructive moves ? You can still access a value after it has been moved out. use-after-move is allowed by the compiler. It places (stdlib) types in an unspecified but valid state (I've seen C++ code reusing these types and assuming that the state after move is something in particular -- it's not). Most optimizations you can do by reusing…
Use-after-move is allowed because of existence of value categories, if you use a return value from a function its creation is usually elided or it is moved, but you can't access that temporary without directly referencing it. When you move an existing object (by specifically saying std::move), what should happen with it? Destroying the object is not a solution because its variable might be still accessible in existin…
You don't destroy it, you treat it as an actual "move", where the compiler will not consider the original variable as accessible after this point, and not allow accesses after the move. The memory it took up is free for reuse, and no destruction code is run on the side of the code doing the moving (in the case of a conditional move this gets a tiny bit more complex, but not too much). "It's variable will be still accessible in local scope" is exactly what I'm getting at; you can enforce at compile time that this isn't the case by simply disallowing access.
You shouldn't have local references active, just like how you shouldn't have local references to the contents of a vector when you push to it. You can already invalidate local references to a part of a struct when something gets moved in modern C++. Being wary of invalidating local references is an established concept in C++; this doesn't exacerbate that problem.
It's even better if you track scopes in references which gets rid of the dangling reference problem entirely but at this point you've reinvented Rust :p
To be clear, I'm talking of a completely different model that could have been used in place of the rvalue reference and move model. Making C++ have linear types now would be tough, but it could have been done before. There are different tradeoffs there, but I suspect it would have been safer.
> all variables should have a "not-a-value" state and throw exceptions on use.
You can make this a compile time error. Like I said, linear typing is a pretty well established pattern.
Re: Getting Past C
#485Earlier quoted context omitted.
You're right, to an extent we are talking past each other. I totally understand how your code can cause a dangling pointer. But you are using a raw C array, which completely goes against what I've been poorly trying to explain in this thread. What I am advocating is something like this: https://gist.github.com/anonymous/32df4da4949a6c1067c2be8f20... so TL;DR, if you don't want to deal with copying structs, malloc the…
> if you don't want to deal with copying structs, malloc them then push them to the dynamic array So, manually manage their memory allocation, but allow dynamic allocation of the array of pointers? Sure, there are some cases where that's useful, but if you're already managing memory for the structs themselves, you can probably just manage the memory for the array at the same time. > Else if you push a struct value on…
Yes.
Sure, there are some cases where that's useful, but if you're already managing memory for the structs themselves, you can probably just manage the memory for the array at the same time.
... then you have memory bugs. As your example code clearly shows. What you're suggesting (exposing the internal backing array of a dynamic array) is completely unorthodox and fraught with potential bugs, and I doubt if rust even does this internally.
All I can suggest is that you look up how dynamic arrays are typically implemented in C. The technique I describe is almost universally followed. This is also what happens with std::vector in C++ - std::vector doesn't manage the memory of the elements themselves, just its internal backing array.
Re: Getting Past C
#486Earlier quoted context omitted.
While I now mostly agree with you that there is more unsafe code than there should be, I still maintain that the frequency of unsafe in a deptree is usually still small enough to be practically auditable, ignoring FFI. It could/should be much less, but it's not too bad. I've done such audits a few times and it's not been too hard and taken very little time. Auditing FFI is a whole other challenge, however :(
> I still maintain that the frequency of unsafe in a deptree is usually still small enough to be practically auditable Not in binary libraries, hence why it is important to have a culture to only use unsafe if it really must be used.
You do have C libraries which you access through FFI. This is inevitably unsafe. We should be auditing more there. Though IMO it's still manageable, for most crates.
Re: Getting Past C
#487I was under the impression that these specific things were actually quite hard to do in Go. I believe that both setuid/setgid and seccomp_load change the current OS thread (only), and since Go multiplexes across multiple threads and gives programmers very little control over which ones are used for what goroutines, I'm not sure how you would, for example, apply a seccomp context across all threads in a Go program. setuid/setgid are currently unsupported for this reason, with the best method being "start a subprocess and pass it file descriptors" (https://github.com/golang/go/issues/1435).
I'd be interested to hear if others have found ways to actually do this reliably for all OS threads underlying a running Go process.
Re: Getting Past C
#488> Under Linux, some SECCOMP initialization and capability dances having to do with dropping root and closing off privilege-escalation attacks as soon as possible after startup. I was under the impression that these specific things were actually quite hard to do in Go. I believe that both setuid/setgid and seccomp_load change the current OS thread (only), and since Go multiplexes across multiple threads and gives prog…
Switched to Rust and there was only had one hidden system call left, getrandom used to initialize the hashmap
Re: Getting Past C
#489> Under Linux, some SECCOMP initialization and capability dances having to do with dropping root and closing off privilege-escalation attacks as soon as possible after startup. I was under the impression that these specific things were actually quite hard to do in Go. I believe that both setuid/setgid and seccomp_load change the current OS thread (only), and since Go multiplexes across multiple threads and gives prog…
Re: Getting Past C
#490Earlier quoted context omitted.
Again, if you're disallowing platform headers and writing tooling to make sure you're never calling libc, what's the advantage of writing in C? You have all the headaches of switching to a new language, with none of the features. And, honestly, one of the features is "vibrant community of developers." Even if Go and Rust were bad languages, which they're not, they'd still be better choices than C-with-custom-in-house…
I'm not advocating use of C, just pointing out a simpler way to check dependencies. To answer your question though, the advantage of using C is certainly not the notorious bad-habits standard library. C is fun and productive exactly where there's just you and some bits and bytes to bang around. Coding in the small. Not platforms and architectures.