One company creates a closed-source component that produces a float, another company creates a closed-source component that receives a float. Units differ. Crash. No type-safe language will prevent that bug from happening. Let 100 programmers write these programs in your type-safe language of choice and all will be vulnerable to this.
"Oh no", I hear you say, "we'll give every unit its own type" and it still won't stop your programmers from deserializing a 4 byte value in English units into the metric value they think it is. "So we'll make all the IO typed as well!" You don't need a type safe language to do that. And why would you do it in the first place? If your API spec says you receive a float in metric units, you write your program accordingly. When you're writing mission critical software, would you really want to replace a
> read(sensor, &value, sizeof(float))
with 100k lines of even buggier code to prevent a bug from happening that shouldn't happen in the first place?
Some will be, some will define inteface as float_meters and define automatic conversion from yards, avoiding whole issue.
What C feature forces or encourages casting Meters* to Yards*?
> You also cannot override operators for combining those units.
The lack of operator overloads has nothing to do with typesafety. There are languages which are considered typesafe and which do not have operator overloading.
Example of successful compilation in C Language which is semantically wrong: http://ideone.com/Hdd4Sh
(No casts required.)
1. you can have the same problem in type-safe language, since it will probably have cast to int too 2. do not use builtin operators in C for that, instead create new functions, e.g. addMeters(Meters a, Meters b); 3. hide the int in *.c file
Yes, you can. But at least you have a better option and better chance of other people using it, so statistically you'll have less errors.
> do not use builtin operators in C for that
No, do not add another rule to a million of rules people have to already follow, make compiler worry about enforcing that, not developer.
I highly doubt that this specific bug would not happen in any typesafe language. The only way I see this not happening is if there is no native float-like type. Is there such language? They could have make it safe in C, and they did not, probably because it's convenient to use float.
> No, do not add another rule to a million of rules people have to already follow, make compiler worry about enforcing that, not developer.
It can be implemented in C so it's forced by compiler.
- do not use builtin operators in C for that,
- instead create new functions, e.g. addMeters()
- hide the int in *.c file
Those are "best practices" instead of compiler-enforced type-check errors. Likewise, suggesting a best practice such as "don't free() memory twice" is not the same as a GC-language (Lisp/Java/C#/Go) freeing memory on the programmer's behalf or a static-ownership checker (Rust) preventing a programmer from making that mistake. public class Meters { public int x; }
public class Yards { public int x; }
public class Kilograms { public int x; }
Meters m = ...
Yards y = ...
Kilograms k = ...
k.x = m.x + y.x;
all my sugestions for C are basically the same in C# - do not use builtin operators in C# for that instead create new functions, e.g. addMeters()
- hide the int in *.c file == make it private in c#"Best practice" is a choice from among justifiable alternatives.
Any program in any language can be regarded as not having passed checks for some imaginable something.
A perfectly good poker game is semantically wrong because the customer asked for an accounting application. The compiler should have checked the code against a formalized version of the requirement spec, damn it!
No, that isn't quite right. I'm the one who authored that code example so even if I used opaque non-English struct tag names such as "struct s1{}" and "struct s2{}" instead of "struct meter{}" and "struct inch{}", my brain intended for s1 and s2 to not be mixed and matched carelessly. Poster mikulas_florek suggested wrapping plain ints with a struct and my example shows that that workaround doesn't accomplish what he says it does.
>It is well-defined ISO C.
Yes, and I wanted to emphasize that truism by showing a live example of a successful compilation in ideone.com!
I thought the thread was about higher-level semantics rather than the set of trivially true sequences of text input that the compiler accepts.
Successful C compilation rarely means that only higher-level semantics not encoded into type system is now violated.
The battles in C are already being lost in the trenches of lower-level semantics.
If worrying about these higher level things and getting them right were the only problem in C development, C development would be in fantastic shape.
In safe languages which don't have type systems that can express pounds versus inches in inviolable ways, that sort of thing is rarely any sort of obstacle to real work; it's a fluff concern.
If I have to program in something which has no way of enforcing pounds being added to inches, and that is the only significant drawback of that language, I'm laughing.
I didn't make that claim that UB goes away with a successful compilation and therefore "only" the higher-level semantics are worth studying. Since nobody in this thread said that, I'm puzzled why you'd think I'd have such a naive position.
>these higher level things and getting them right were _the only_ problem in C development,
But I'm not arguing they are "the only" problem. Again, poster mikulas_florek suggested a code technique that claims to address a problem but does not work. That's the limited scope of my demo code.
I don't know how theoretically fixing that tiny snippet got elevated to be the "savior to all C problems". I made no such grand claim.
>, that sort of thing is rarely any sort of obstacle to real work; it's a fluff concern.
Whether it is or isn't in relation to actual millions of lines of real-world code that may or may benefit from it is not relevant. Curl is an example of real working C Language software that may have zero code requiring type-checked units-of-measure. That's still not relevant to the previous poster mikulas_florek mis-educating C programmers.
Btw, the units-of-measure is just one variation of the "type check" issue. Many times a programmer will have a function definition such as (customer_id x, action_code y). If the programmer accidentally reverses the 2 typedefs, the compiler won't catch that. Example: http://ideone.com/2dyT9n
That type of human error happens all the time and I disagree that would be a "fluff concern".
So, getting to hyper-focused on specific type failure examples such as units-of-measure instead of considering the more generalized higher-level errors not caught by C compiler is missing the point of what the thread is about.
What is NOT idiotic iswhat you discribe as 'ridiculous amount of verification' as it's often the only thing that will really work to catch mistakes.
But it will limit the damage they do considerably. Having bit of space or trees between lanes on a road saves a lot of lives, even if people drive as idiotically as they would without it.
> What is NOT idiotic is what you discribe as 'ridiculous amount of verification'
Designing systems that rely only on that is idiotic when there are better options.