3 ms·
The real problem is that people keep on inventing new memory safe languages that no longer support many of the widely-used features of C. Ignore efficiency and
by o11c 3y ago
The real problem is that people keep on inventing new memory safe languages that no longer support many of the widely-used features of C.
Ignore efficiency and all that. If you don't support `union` and `va_list`, you're never going to replace C. It's okay to mark them as deprecated, but you need to support them to provide a migration path.
The fact that C allows hand-written `memcpy`-style loops is another major concern in theory, but it is one that is much easier to port. Laundering pointers through non-process memory is rare enough that an explicit API is reasonable to require.
And yes, it is possible to support all these things with perfect dynamic memory safety and without increasing pointer size!
- kbolino 3y ago> And yes, it is possible to support all these things with perfect dynamic memory safety and without increasing pointer size! You had me up to this point. A memory-safe union is a discriminated union, which needs extra information (a discriminator) to tell which case is currently active. That doesn't necessarily increase pointer size, but it does break ABI compatibility.
- o11c 3y agoYou don't have to store that in-line, you can store it in metadata. Kind of like how ASAN works, but with typing info instead of just validity info. Now yes, for performance you don't want to do this ... but it can be just one step of the migration.
- kbolino 3y agoIf you're able to accept ABI breakage or changing the C code, then I don't think any major language which is capable of calling C code is missing support for unions. The same cannot be said for varargs, though.
- o11c 3y agoI explicitly refer to untagged unions though, not tagged ones. The lack of a language-known tag is part of the API, not just the ABI. Even library-specific tags should only be considered an incremental upgrade, not the core union support. Yes, it is possible to refactor things like `SDL_Event` to use subclasses instead of unions. But the point is - you shouldn't have to, not at first. And of course, you need to be able to use a union to perform a bitwise cast between float and int. Not some other ad-hoc API; it needs to be trivial to port from C regardless of what the context looks like.
- kbolino 3y agoI'm trying to think of how it would be possible to have memory-safe untagged unions. I don't really think there's a workable solution in the general case, though there might be some specific cases where it works. Undefined behavior is perfectly acceptable for C (though it makes code less portable); it is completely unacceptable in safe languages (outside of unsafe callouts). I'm also not sure why it's necessary to use a union for bitwise conversions. Java and Go, off the top of my head, have safe functions for bitwise int<->float (int32<->float32 in Go) and long<->double (int64<->float64 in Go). Moreover, if I remember correctly, you are only actually allowed to use one case at a time in a C union. If I'm right, then using a union to do bitwise casts is actually undefined behavior in C, even if it almost always works. Put simpler, you cannot write one type into a union then read a different type; you must always read the last type that was written. edit: I dug up my copy of K&R 2/e and yeah, unions are not meant to be used for things like casts. Some supporting text: > A union is a variable that may hold (at different times) objects of different types and sizes, .... (Sec 6.8, p. 147) > Any one of these types may be assigned to u and then used in expressions, so long as the usage is consistent: the type retrieved must be the type most recently stored. It is the programmer's responsibility to keep track of which type is currently stored in a union; the results are implementation-dependent if something is stored as one type and extracted as another. (Sec 6.8, pp. 147-148) In the case of SDL_Event, there actually is a discriminator of sorts. Every case of the union starts with `Uint32 type` and I don't think any case breaks 4-byte alignment on most platforms. With a little compiler support, it would probably be possible to support SDL_Event variables directly in a memory-safe language.
- Gibbon1 3y agounions would be better if C had first class types. C would be safer if it had memory safe casts. C would be safer if we forced compilers to implement Walter Brights suggestion about array arguments. C would be better if it had stdslice.h Programs would be safer if the cultural prohibition against passing and returning structs was exterminated.
- kbolino 3y ago> Programs would be safer if the cultural prohibition against passing and returning structs was exterminated. The lack of a single, dominant, consistently high-quality C compiler likely caused this problem. As long as `int foo(struct{int x; int y})` doesn't optimize down to `int foo(int x, int y)` there are significant performance issues with struct passing. The return situation is especially problematic since C doesn't have multiple-valued return to begin with, so structs become a special case.