[flagged]
[flagged]
If you're actually trying to talk to people, if you're not just here to say "I'm smart and you're stupid" to gratify your ego, then why talk in a way that makes other people less likely to listen?
51–60 of 174 posts
[flagged]
[flagged]
If you're actually trying to talk to people, if you're not just here to say "I'm smart and you're stupid" to gratify your ego, then why talk in a way that makes other people less likely to listen?
[flagged]
The problem is not that the rules are hard to follow--they're actually quite easy! The problem is that, to follow the rules, you need to set up certain invariants, and in any appreciably large codebase, remembering all of the invariants is challenging. As an example, here's a recent memory safety vulnerability I accidentally created:
int map_value(map_t *map, void *key) {
// This returns a pointer to the internals of map, so it's invalidated
// any time map is changed. Therefore, don't change the map while this
// value is live.
int *value = add_to_map(map, key, default_value());
// ... 300 lines of code later...
// oops, need to recurse, this invalidated value...
int inner = map_value(value, f(key));
// ... 300 lines of code later...
// Hi, this is now a use-after-free!
*value = 5;
return value;
}
It's not that I'm too stupid to figure out how to avoid use-after-frees, it's that in the course of refactoring, I broke an invariant I forgot I needed. And the advantage of a language like Rust is that it bops me on the head when I do this.Really, don't do this, it's a portability and safety nightmare (aside from C not being memory safe already). C programmers are better off with either of these two techniques: * Use __attribute__((cleanup)). It's available in GCC and Clang, and we hope will be added to the C spec one day. This is widely used by open source software, eg. in systemd. * Use a pool allocator like Samba's talloc ( https://talloc.samba.org/…
> we hope will be added to the C spec one day defer seems to be making significant progress (having a passionate and motivated advocate in Meneide, and a full TS)
(EDIT: I'm wrong, see reply)
[flagged]
Everyone starts with the best of intentions. malloc() and free() pairs. Then inevitable complexity comes in - the function gets split to multiple, then across modules, and maybe even across systems/services (for other shareable resources).
The mental overhead of ensuring the releases grows. It _is_ hard, and that's most definitely not a lie beyond any trivial implementation.
Surprisingly "just design systems that manage their memory correctly", as you said, is a very legitimate solution. It just so happens that those systems need good language support, to offload a good chunk of the complexity from the programmer's brain to the machine.
Just C programmer's daily struggle to mimic a fraction of C++.
Earlier quoted context omitted.
> relying on compiler vendor extensions kind of defeats the purpose of that. Let's be honest, how many compilers are available, and how many of those would you actually use? The answer isn't more than 4 and the 2 compilers you are most likely to use among those already support this and probably won't stop supporting without a good alternative. I like standardisation, but you have to be realistic when it helps you wit…
For me, the point of writing something in C is portability. There were C compilers 30 years ago, there are C compilers now, and there will almost certainly be C compilers 30 years from now. If I want to write a good, portable library that's going to be useful for a long time, I'll do it in C. This is, at least, the standard in many gamedev circles (see: libsdl, libfreetype, the stb_* libraries). Under that expectatio…
Earlier quoted context omitted.
It's so widely used by OS software that you're likely using already, that it's unlikely to be removed and much more likely to be standardized. This is in fact how standardization ought to work - standardize the proven best practices.
I agree. But if we follow that logic then any compiler specific feature of either or clang is fair game, even if it’s not standard. MSVC doesn’t support it when compiling in C mode, for example.
Well, yeah...
How do you think Annex K got in?
[flagged]
Yes, and the general trend of falling traffic fatalities is because people are driving better, right? Nobody's perfect, most people are far from perfect, and if it's possible to automate things that let you do better, we should do that
Earlier quoted context omitted.
Correct. You can use it in a simple way to free memory, but we've also used it to create scoped locks[1]. This being C, it's not without its problems. You cannot use it for values that you want to return from the function (as you don't want those to be freed), so any such variables cannot be automatically cleaned up on error paths either. Also there's no automated checking (it's not Rust!) Note it's {...} scoped, not…
While Go rules effectively prevents usage of defer in loops, it is useful occasionally to write: if complex_nested_condition { defer cleanup() }
defer if complex_nested_condition { cleanup() } else { noop() }
In Go, you could do: defer func(run bool) {
if !run { return }
}(condition)
Which admittedly wastes stack space with a noop function in the false case, but whatever.I feel like the number of times I've needed conditional defers is almost zero, while the number of times I've had to make a new function to ensure scoping is correct is huge.
Of especial note, 'mu.Lock(), defer mu.Unlock()' not being scope-based is the largest source of deadlocks in code. People don't use 'defer' because the scoping rules are wrong, code panics before the manual unlock call, and then the program is deadlocked forever.