LWN: Comments on "Moving the kernel to modern C" https://lwn.net/Articles/885941/ This is a special feed containing comments posted to the individual LWN article titled "Moving the kernel to modern C". en-us Tue, 16 Sep 2025 13:56:05 +0000 Tue, 16 Sep 2025 13:56:05 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net Moving the kernel to modern C https://lwn.net/Articles/888292/ https://lwn.net/Articles/888292/ nix <div class="FormattedComment"> Um, yes, of course. I&#x27;ve had a mental hash collision between those two acronyms for literally decades, to such an extent that if you asked me what RTTI stood for I&#x27;d often say &quot;resource acquisition is oh wait&quot;.<br> </div> Thu, 17 Mar 2022 16:27:54 +0000 Moving the kernel to modern C https://lwn.net/Articles/887670/ https://lwn.net/Articles/887670/ timon <div class="FormattedComment"> I think you mean RAII (Resource acquisition is initialization) instead of RTTI (Run-time type information).<br> </div> Fri, 11 Mar 2022 16:51:01 +0000 Moving the kernel to modern C https://lwn.net/Articles/887393/ https://lwn.net/Articles/887393/ bartoc <div class="FormattedComment"> The comma is a bit of a huge pita if you&#x27;re passing a whole loop body.<br> </div> Wed, 09 Mar 2022 23:56:45 +0000 Moving the kernel to modern C https://lwn.net/Articles/886912/ https://lwn.net/Articles/886912/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; After all in some languages (BASIC for example) we were not shocked by reading &quot;OR&quot;, &quot;AND&quot; or &quot;XOR&quot; as operators between two numbers. ... remove the ambiguity that you have in certain languages like JS where a=b+1 is ambiguous when b=&quot;1&quot; where you don&#x27;t know if you&#x27;ll get string &quot;11&quot; or integer 2.</font><br> <p> Does OR do a bitwise OR or a boolean OR? I don&#x27;t see any saving in ambiguity there. Likewise for the left shift; for all the fuss over it, in practice I&#x27;ve never seen it be the least bit ambiguous.<br> <p> As for JavaScript, as I said, I was thinking of statically typed languages, and if you&#x27;re programming JavaScript, you should know the answer to that. (It&#x27;s &quot;11&quot;.) But it is a little more confusing than it would be in other languages, since &quot;1&quot; / 1 implicitly converts &quot;1&quot; to a number, which is problematic, since lossy conversions should generally be avoided, especially when you&#x27;re shoving a round peg into a square hole. The problem is not with operator overloading, so much as it&#x27;s with lossy conversions. &quot;String&quot; / 1 should be caught at compile time, not run time.<br> </div> Sat, 05 Mar 2022 17:45:47 +0000 Moving the kernel to modern C https://lwn.net/Articles/886910/ https://lwn.net/Articles/886910/ wtarreau <div class="FormattedComment"> <font class="QuotedText">&gt; I&#x27;d point out your C++ examples are self-inflicted; unlike programmers, the C++ designers could have added operators to the system.</font><br> <p> That was my point. Having a set of &quot;free to use&quot; operators that are never defined by default and are always type-specific would be perfect because they&#x27;re sufficient to ring a bell when you read that code. But as the previous commenter said, using explicit names instead of left-shifting string still remains quite better. After all in some languages (BASIC for example) we were not shocked by reading &quot;OR&quot;, &quot;AND&quot; or &quot;XOR&quot; as operators between two numbers. I&#x27;d be fine with a &quot;CAT&quot; operator to concatenate two strings, and remove the ambiguity that you have in certain languages like JS where a=b+1 is ambiguous when b=&quot;1&quot; where you don&#x27;t know if you&#x27;ll get string &quot;11&quot; or integer 2.<br> <p> </div> Sat, 05 Mar 2022 17:13:18 +0000 Moving the kernel to modern C https://lwn.net/Articles/886899/ https://lwn.net/Articles/886899/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; The thing ncm likely meant was that Wol&#x27;s imagined kernel-developers&#x27; worries are not actually what they are documented as having worried about. C++ is not a security nightmare, not any more than C, anyway; it hasn&#x27;t been worse than C optimization-wise for about twenty years; and there is no sudden extra need to drop into asm just because this is C++ (C++ is still nearly a superset of C, and this is just as true of the GNU variant).</font><br> <p> <font class="QuotedText">&gt; Their stated worries are more that C++ has abstractions that enable things to magically happen behind your back with no immediate indication at the call site, and since the kernel developers are really looking for a portable assembler a lot of the time, where everything the machine does is obvious, this is *far* from what they want: they have their hands full coping with parallelism-induced complexities, memory model complexities, looking out for speculative execution gadgets etc etc, without worrying about the apparently same code doing wildly different things depending on what type they&#x27;re operating on.</font><br> <p> Actually, this is pretty much exactly what I was trying to say ... that C++ does things behind your back, and when you&#x27;re trying to make sure that your code fits in L1 cache or whatever, code bloat is SERIOUS STUFF.<br> <p> How often do you see kernel developers talking about &quot;fast path&quot;? Quite a lot. And it only takes C++ to do something you don&#x27;t expect and the fast path will become orders of magnitude slower. WHOOPS!<br> <p> Cheers,<br> Wol<br> </div> Sat, 05 Mar 2022 13:37:12 +0000 Moving the kernel to modern C https://lwn.net/Articles/886897/ https://lwn.net/Articles/886897/ nix <div class="FormattedComment"> [Caveat: haven&#x27;t written lots of C++ in years, and that was back in the early &#x27;10s. The language has changed and I haven&#x27;t kept up, I know...]<br> <p> The thing ncm likely meant was that Wol&#x27;s imagined kernel-developers&#x27; worries are not actually what they are documented as having worried about. C++ is not a security nightmare, not any more than C, anyway; it hasn&#x27;t been worse than C optimization-wise for about twenty years; and there is no sudden extra need to drop into asm just because this is C++ (C++ is still nearly a superset of C, and this is just as true of the GNU variant).<br> <p> Their stated worries are more that C++ has abstractions that enable things to magically happen behind your back with no immediate indication at the call site, and since the kernel developers are really looking for a portable assembler a lot of the time, where everything the machine does is obvious, this is *far* from what they want: they have their hands full coping with parallelism-induced complexities, memory model complexities, looking out for speculative execution gadgets etc etc, without worrying about the apparently same code doing wildly different things depending on what type they&#x27;re operating on.<br> <p> Many of C++&#x27;s transparently-do-things features are routinely used and almost essential to use anything resembling modern C++: references are the classic case (now function parameters&#x27; values can change in the caller without an &amp; at the call site), but also C++ before std::move used to not make it terribly clear whether things were being copied or not (and it was at the very least wordy to enforce one alternative), and even now we have things like stringviews which seem to come with built-in footguns. (Of course, the kernel would never use such pieces, but code review would need to make sure they never crept in... and you only need to forget *once*). Many of the pieces that *don&#x27;t* amount to &#x27;do this invisibly albeit usually helpfully&#x27; are related to templates, and, uh... the kernel is nonswappable code in which size is at a premium, and having the compiler promiscuously generate code to monomorphize templates on the fly was anathema for a long time (though Rust does the same thing, and people seem to be complaining less: maybe RAM is just that much cheaper now and kernel code size is less important? but icache bloat still matters, and Linus has worried about it in public, and that was years ago and it&#x27;s worse now).<br> <p> And that&#x27;s without even mentioning the really big painful problem, so big and painful that there are still compiler switches to disable the feature entirely, so big and painful that it took decades to figure out how to write code safely in the presence of these things and the last time I looked at it the safe code was extremely unobvious and if it was wrong you were unlikely to know for many years until things blew up, because there was no way to automatically check for safety: exceptions. Lovely idea, makes code&#x27;s non-exceptional path much clearer, but the implementation explodes exceptional flow paths and *all of them are invisible* and many might be in what looks like the middle of an atomic, indivisible entity to someone not thinking &quot;what if this were overloaded and threw?&quot;. If you use RTTI for absolutely everything religiously you don&#x27;t need to worry, but you only have to forget and do manual cleanup once and you&#x27;re in trouble when you next get an exception passing through that region. The kernel would obviously never use exceptions in the first place, mind you. Of course that now makes it impossible for destructors to fail, which probably rules out *use* of destructors for anything nontrivial, which means you can&#x27;t use RTTI, which means you can&#x27;t write anything resembling modern C++. You don&#x27;t pay for what you don&#x27;t use, but many of the bits require many of the other bits to use them non-clumsily, and then many of those bits are papering over design faults in the earlier bits -- std::move, again -- and the result of adding all those bits together is *ferociously* complex.<br> <p> </div> Sat, 05 Mar 2022 12:28:14 +0000 Moving the kernel to modern C https://lwn.net/Articles/886881/ https://lwn.net/Articles/886881/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; The entire problem with C++ is &quot;where do you draw the line?&quot;.</font><br> <p> That&#x27;s a problem with C++, not operator overloading or object orientation. <br> <p> <font class="QuotedText">&gt; That&#x27;s really not a problem with the pre-processor: it&#x27;s always very obvious whether you use it or not and I&#x27;ve seen &quot;no pre-processor here&quot; review comments countless times.</font><br> <p> It is quite similar to operator overloading; you can see where the macro or operator is defined, but not necessarily where it is used.<br> </div> Sat, 05 Mar 2022 02:42:45 +0000 Moving the kernel to modern C https://lwn.net/Articles/886853/ https://lwn.net/Articles/886853/ foom <div class="FormattedComment"> <font class="QuotedText">&gt; I&#x27;d point out your C++ examples are self-inflicted</font><br> <p> Indeed, the C++ standard library designers often (but not always) act as if they have no ability to influence the core language design. And they may be correct, to some degree -- the language and library changes are done by different working groups within the standards committee, so there&#x27;s going to be a greater organizational friction to get your change in, if you need to modify both.<br> </div> Fri, 04 Mar 2022 21:29:08 +0000 Moving the kernel to modern C https://lwn.net/Articles/886849/ https://lwn.net/Articles/886849/ marcH <div class="FormattedComment"> BTW a great trick to unravel (evil) cpp macros is to deliberately insert a compilation error. gcc then shows the entire stack of macros involved. Much easier than cc -E or something.<br> <p> Same trick with build systems and many other situations with &quot;too many layers of indirections&quot;: deliberately injecting errors is often a great shortcut.<br> <p> (none of that available at run-time of course)<br> </div> Fri, 04 Mar 2022 20:22:21 +0000 Moving the kernel to modern C https://lwn.net/Articles/886829/ https://lwn.net/Articles/886829/ marcH <div class="FormattedComment"> <font class="QuotedText">&gt; Assuming you&#x27;re not using Ruby, the type of the variable should be named nearby in the code. [...] In a.b(...), the code is found in file named after the type of a. </font><br> <p> ??<br> <p> The type of the variable does not provide vtable resolution. That&#x27;s done only at run-time. Same problem for explicit .ops function pointers in C. You cannot just &quot;grep&quot; through vtables / .ops because they&#x27;re resolved at run-time. That&#x27;s the whole OO proposition.<br> <p> <font class="QuotedText">&gt; Assuming you&#x27;re not using Ruby, the type of the variable should be named nearby in the code.</font><br> <p> Afraid you lost me there.<br> <p> <font class="QuotedText">&gt; In C, the definition of the function may be found in one of the files you #included in this code (or not; you can always declare external functions directly), but that header file name may have no relation to the file where the code is written.</font><br> <p> Code indexers can do a surprisingly good job most of the time. For the rest there is always git grep. It works as long as nothing is resolved at run-time.<br> <p> <font class="QuotedText">&gt; Of course, with the handy -D option to the C compiler, who knows what the function is actually named.</font><br> <p> I&#x27;ve seen many -D and I&#x27;ve never seen one redefining function names. As already wrote above, no one like the pre-processor and its abuse is very easily and routinely caught at code review. The entire problem with C++ is &quot;where do you draw the line?&quot;. That&#x27;s really not a problem with the pre-processor: it&#x27;s always very obvious whether you use it or not and I&#x27;ve seen &quot;no pre-processor here&quot; review comments countless times.<br> <p> </div> Fri, 04 Mar 2022 17:28:29 +0000 Moving the kernel to modern C https://lwn.net/Articles/886828/ https://lwn.net/Articles/886828/ marcH <div class="FormattedComment"> <font class="QuotedText">&gt; And most exploited security flaws in software are found by careful code review and could be spotted by their developers if the code was not constantly cheating on them doing nasty tricks that do not ressemble what it seems to do.</font><br> <p> I wonder where you got that from. Sure there&#x27;s Spectre and alike but most security flaws I ever looked at (admittedly not that many) were all &quot;mundane&quot; out of bounds accesses, uninitialized use, use after free, integer overflows, etc. All the usual and mundate memory corruption features of C which according to Microsoft and Google account for 70% of all security issues in C/C++ projects (I don&#x27;t know what the other 30% are)<br> <p> </div> Fri, 04 Mar 2022 17:06:30 +0000 Moving the kernel to modern C https://lwn.net/Articles/886826/ https://lwn.net/Articles/886826/ marcH <div class="FormattedComment"> <font class="QuotedText">&gt; &gt; That&#x27;s the same reason why many developers perfer to use upper case for macros. It&#x27;s a signal that you should look it up and that it might evaluate your arguments more than once, for example.</font><br> <p> <p> <font class="QuotedText">&gt; Why can developers be trusted with macros and not operator overloading?</font><br> <p> They can&#x27;t with either. No one likes the pre-processor. It&#x27;s always seen as a necessary evil to work around C&#x27;s limitations. Macros are subject to especially high review scrutiny and new ones can be introduced only if they solve a very generic problem and only when they are used all across the board (which ensures a lot of test coverage).<br> </div> Fri, 04 Mar 2022 17:02:43 +0000 Moving the kernel to modern C https://lwn.net/Articles/886823/ https://lwn.net/Articles/886823/ atnot <div class="FormattedComment"> <font class="QuotedText">&gt; I&#x27;d point out your C++ examples are self-inflicted; unlike programmers, the C++ designers could have added operators to the system.</font><br> <p> This is a really long tradition in C++ land. For example, afaict the only reason C++ attempts to use operators for streams in the first place is because the language itself was not rich enough to be able to express generic, type-safe string formatting well. It just so happened that the existing function overloading and a convenient left-associative operator let you cobble together a hacky workaround which then became standard.<br> <p> Meanwhile nearly every other language decided to go and do what needed to be done to enable type safe string formatting instead. Including C++, which accidentally eventually enabled it to be written anyway, giving rise to {fmt} and then std::format.<br> <p> Then they went and did the same thing again with iterators, sfinae, variant/visit/optional, etc.<br> <p> I think the moral of iostreams is less that operator overloading is a bad idea, but that people will do absolutely horrible things if a language is not interested in finding ways to adequately address their needs.<br> </div> Fri, 04 Mar 2022 16:44:18 +0000 Moving the kernel to modern C https://lwn.net/Articles/886821/ https://lwn.net/Articles/886821/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; operators have a more convenient infix syntax, but there&#x27;s a limited number of them which you can use, and that causes people to prefer to overload them for inappropriate operations.</font><br> <p> Good point in general. Scala mitigates that by letting methods with one argument be used infix (in version 2, in Scala 3 you have to declare it infix), and allowing pretty much arbitrary operator/method names (for better and worse, :^$*+ is a valid method name that can be used infix in Scala.)<br> <p> I&#x27;d point out your C++ examples are self-inflicted; unlike programmers, the C++ designers could have added operators to the system.<br> </div> Fri, 04 Mar 2022 16:07:40 +0000 Moving the kernel to modern C https://lwn.net/Articles/886796/ https://lwn.net/Articles/886796/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; Nobody imagines that when you&#x27;re doign your errands and see &quot;3 + 1 offered&quot;, this &quot;+&quot; means &quot;perform a database access</font><br> <p> In all the programming languages under discussion, 3 + 1 returns 4. In mathematics, a + b is an arbitrary function, almost always associative and commutative; 3 + 1 can equal 0, in Z mod 4. I&#x27;ve certainly seen + used as a concatenation operator in real life, like in rebuses. <br> <p> <font class="QuotedText">&gt; if the code was not constantly cheating on them doing nasty tricks that do not ressemble what it seems to do. That&#x27;s the same reason why many developers perfer to use upper case for macros. It&#x27;s a signal that you should look it up and that it might evaluate your arguments more than once, for example.</font><br> <p> Non-hygenic macros are insane. Had you said <br> <p> <font class="QuotedText">&gt; That&#x27;s exactly why I despise [C&#x27;s macro system]. You cannot trust anymore what you&#x27;re reading.</font><br> <p> I wouldn&#x27;t have disagreed. So why the difference? Why can developers be trusted with macros and not operator overloading?<br> </div> Fri, 04 Mar 2022 15:59:43 +0000 Moving the kernel to modern C https://lwn.net/Articles/886795/ https://lwn.net/Articles/886795/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; I should not have written _your own code_, I meant: you get lost _in the code base that you are working on_ </font><br> <p> And it still stands; if it&#x27;s the code base that you are working on, you should know what type is getting passed in and where to look for that code. Assuming you&#x27;re not using Ruby, the type of the variable should be named nearby in the code.<br> <p> And again, &quot;I can&#x27;t find which source tab to look at&quot; is weird coming from someone bashing Java. In a.b(...), the code is found in file named after the type of a. In C, the definition of the function may be found in one of the files you #included in this code (or not; you can always declare external functions directly), but that header file name may have no relation to the file where the code is written. Of course, with the handy -D option to the C compiler, who knows what the function is actually named.<br> </div> Fri, 04 Mar 2022 14:57:01 +0000 Moving the kernel to modern C https://lwn.net/Articles/886761/ https://lwn.net/Articles/886761/ foom <div class="FormattedComment"> <font class="QuotedText">&gt; Operator overloading&quot; is no different than any other overloading.</font><br> <p> It&#x27;s different in a really key way in most languages (not Haskell): operators have a more convenient infix syntax, but there&#x27;s a limited number of them which you can use, and that causes people to prefer to overload them for inappropriate operations.<br> <p> Let&#x27;s pretend c++ had no infix operators whatsoever (overloaded or not). So instead of `1 &lt;&lt; 2` you&#x27;d say `1.left_shift(2)`. When creating an output stream type nobody would _even consider_ having programmers spell &quot;write to output&quot; as `cout.left_shift(&quot;hello world&quot;)`. That&#x27;s just ridiculous on it&#x27;s face! Of course you&#x27;d use a more appropriate name.<br> <p> Yet, because of the limited operator vocabulary that is available to work with, there&#x27;s a great temptation to use operator overloads for these nonsensical operations. An absolutely irresistible temptation, I&#x27;d say. And that&#x27;s why operator overloading unfortunate in practice -- even though it shouldn&#x27;t be in theory.<br> <p> For example: C++20 just repeated this mistake, introducing an overload of bitwise_or `|` for (effectively) function composition in the new ranges library. With the weak rationale that `|` means pipe in Unix shell which is kinda the same thing so it &quot;makes sense&quot;. But it doesn&#x27;t. That&#x27;s not what the operator | is supposed to mean in c++.<br> </div> Fri, 04 Mar 2022 14:37:56 +0000 Moving the kernel to modern C https://lwn.net/Articles/886762/ https://lwn.net/Articles/886762/ dvdeug <div class="FormattedComment"> = or + doing database requests is insane, but so is naming the function f() or add() or shelia(). I was not familiar that any dynamically typed language had operator overloading; in a statically typed language, the types of a, b and c would have made automatic renaming possible. Clarity of naming is important, and I&#x27;d argue that there&#x27;s a conservation of information; the more ambiguous the types, the more explicit the function naming needs to be to compensate.<br> <p> <font class="QuotedText">&gt; The only thing it provides is ease of *writing* code</font><br> <p> One of the recent Scheme additions was writing (add (times a c) b) as {a * c + b}, because it actually is easier to read code like that, and<br> <p> &quot;hi &quot; + name.toString + &quot; and good morning&quot; <br> <p> is also easier to read than <br> <p> &quot;hi&quot;.append(name.toString).append (&quot;and good morning&quot;)<br> <p> <p> </div> Fri, 04 Mar 2022 14:36:23 +0000 Moving the kernel to modern C https://lwn.net/Articles/886793/ https://lwn.net/Articles/886793/ ianmcc <div class="FormattedComment"> How is that fixed by spelling it a=add(b,c) ?<br> </div> Fri, 04 Mar 2022 14:30:54 +0000 Moving the kernel to modern C https://lwn.net/Articles/886758/ https://lwn.net/Articles/886758/ wtarreau <div class="FormattedComment"> It&#x27;s also more difficult to read for me, but way less than if I cannot trust any of the most elementary operators anymore.<br> <p> A good example are the mmx/sse/avx* API with all those complicated functions that map 1-to-1 to the underlying instructions. It&#x27;s particularly hard to read, but it would be even worse if operators were abused to perform some of them. And there are still much less operators than possible functions anyway, so being a bit more explicit doesn&#x27;t hurt.<br> </div> Fri, 04 Mar 2022 13:04:36 +0000 Moving the kernel to modern C https://lwn.net/Articles/886753/ https://lwn.net/Articles/886753/ mpr22 <div class="FormattedComment"> The kernel embraced the size overheads of OO back in the 1990s, and C++&#x27;s OO model is just as much &quot;pay for what you use&quot; as the one the kernel uses.<br> <p> If a class has no virtual members, it doesn&#x27;t need a function table and doesn&#x27;t have function-pointer dispatch overheads.<br> <p> If it has some virtual members, only the members that are virtual have to be identified in the function table and called through function pointers.<br> </div> Fri, 04 Mar 2022 09:42:56 +0000 Moving the kernel to modern C https://lwn.net/Articles/886752/ https://lwn.net/Articles/886752/ mpr22 <div class="FormattedComment"> I do have an issue with add(a, b) anywhere that isn&#x27;t the definition of a type&#x27;s implementation of the Arithmetic interface, though.<br> <p> When I&#x27;m trying to understand the calculations a piece of code is doing on data entities for which arithmetic is a &quot;natural&quot; concept, but which are not Sacred Primitive Types of the implementation language, wading through the resulting vast piles of &quot;x = add_foo(a, multiply_foo(b, c))&quot; etc is the kind of chore that degrades my attention span.<br> </div> Fri, 04 Mar 2022 09:38:32 +0000 Moving the kernel to modern C https://lwn.net/Articles/886749/ https://lwn.net/Articles/886749/ wtarreau <div class="FormattedComment"> <font class="QuotedText">&gt; If you don&#x27;t have an issue with `add(a, b)` where `add` can be overloaded then there isn&#x27;t much rational basis for objecting to `a + b` where `+` can be overloaded.</font><br> <p> No, that&#x27;s precisely the opposite. If you don&#x27;t have issue with &quot;add(a, b)&quot;, the please by all means use that and leave the operators to their original meaning so that the vast majority of the characters in the code you are reading do what you were always taught they do. Nobody imagines that when you&#x27;re doign your errands and see &quot;3 + 1 offered&quot;, this &quot;+&quot; means &quot;perform a database access and do some special operation to return a different value&quot; nor &quot;concatenate them and say 31&quot;. No, you imagine an addition, with all the simplicity that comes with it, but within some technical constraints imposed by computers (e.g. domain limitations causing wrapping, saturation or overflows). When I read &quot;a + b&quot;, I hear &quot;a plus b&quot; and nothing else. I&#x27;m not hearing &quot;a, the first argument of a function using a symbol looking like the plus I know, and a second argument b, now let&#x27;s check if such a function exists otherwise I&#x27;ll assume it&#x27;s in fact a regular plus&quot;.<br> <p> It is important to be able to read code the most naturally possible. It&#x27;s a matter of efficiency and reliability. And most exploited security flaws in software are found by careful code review and could be spotted by their developers if the code was not constantly cheating on them doing nasty tricks that do not ressemble what it seems to do. That&#x27;s the same reason why many developers perfer to use upper case for macros. It&#x27;s a signal that you should look it up and that it might evaluate your arguments more than once, for example.<br> <p> </div> Fri, 04 Mar 2022 08:12:32 +0000 Moving the kernel to modern C https://lwn.net/Articles/886748/ https://lwn.net/Articles/886748/ wtarreau <div class="FormattedComment"> <font class="QuotedText">&gt; But operator overloading and inheritance are very different: with them you don&#x27;t know _which source tab in your own editor you should look at_! In other words, you get lost in _your own code_.</font><br> <p> Exactly. More than a decade ago, one of our project died after the ruby developer who was leaving admitted he was totally unable to tell us which assignments or operations were causing database accesses! Because doing a=b+c could *possibly* perform requests ina database to fetch some values or store the results. It became so deep that the code was a living being of itself that noone could tame anymore, and fixing bugs became totally impossible. Definitely a very bad idea. The only thing it provides is ease of *writing* code, but we must never forget that we write once and read it many times.<br> </div> Fri, 04 Mar 2022 07:42:47 +0000 Moving the kernel to modern C https://lwn.net/Articles/886743/ https://lwn.net/Articles/886743/ marcH <div class="FormattedComment"> <font class="QuotedText">&gt; &gt; But operator overloading and inheritance are very different: with them you don&#x27;t know _which source tab in your own editor you should look at_! In other words, you get lost in _your own code_.</font><br> <p> <font class="QuotedText">&gt; Ultimately, if it&#x27;s your own code, you should know what type is getting passed in and where to look for that code.</font><br> <p> I should not have written _your own code_, I meant: you get lost _in the code base that you are working on_ as opposed to some external library, compiler or other abstraction you don&#x27;t care about.<br> <p> Most developers spend most of their time reading and debugging code they did not write themselves. Which is _exactly_ why kernel maintainers don&#x27;t want C++<br> <p> <font class="QuotedText">&gt; If you don&#x27;t believe that OO is useful for GUIs</font><br> <p> I was just rephrasing you.<br> </div> Fri, 04 Mar 2022 06:27:59 +0000 Moving the kernel to modern C https://lwn.net/Articles/886726/ https://lwn.net/Articles/886726/ Wol <div class="FormattedComment"> I thought it started with a suggestion that OO languages (C++) be used in the kernel.<br> <p> In which case, OO-bashing is justified. OO *IS* useful, but in the kernel when a few extra bytes of object code can cost you dearly in page faults etc, those faults are pretty fatal for the concept. THAT was the purpose of the bashing ...<br> <p> Cheers,<br> Wol<br> </div> Thu, 03 Mar 2022 23:54:08 +0000 Moving the kernel to modern C https://lwn.net/Articles/886725/ https://lwn.net/Articles/886725/ dvdeug <div class="FormattedComment"> What does any of this have to do with how slow a program is? Lots of fast programs are unreadable; I think it was Code Complete that talked about writing a DES decrypter in C that was easy to read, and speeding it up one hundred times by turning it into an unreadable pile of assembly. The Linux kernel uses a lot of those nightmare defines to get maximal inline speed at the cost of clarity and ease of finding the code running. Operator overloading has zero effect on speed. <br> <p> <font class="QuotedText">&gt; I date from the years when tomorrow&#x27;s weather forecast took 20hrs to run.</font><br> <p> Weather forecasting always wants faster computers to do more detailed and accurate forecasts. The National Hurricane Center mentioned for their hurricane forecasts that they post every four hours, they run various simulations, and one of them takes six hours to run, meaning it&#x27;s never as up to date as the other simulations.<br> </div> Thu, 03 Mar 2022 23:00:20 +0000 Moving the kernel to modern C https://lwn.net/Articles/886724/ https://lwn.net/Articles/886724/ dvdeug <div class="FormattedComment"> This subthread started with a generalized bashing of OO languages, which is why a mention of where OO languages are useful came up.<br> <p> I&#x27;d be interested to see good measurements of why modern GUIs are so much slower; I&#x27;m curious if once you compensate for the increase in screen size and the increase in data sizes, if they really are all that much slower.<br> </div> Thu, 03 Mar 2022 22:49:43 +0000 Moving the kernel to modern C https://lwn.net/Articles/886719/ https://lwn.net/Articles/886719/ nybble41 <div class="FormattedComment"> &quot;Operator overloading&quot; is no different than any other overloading. Operators are just functions with symbols for names rather than alphanumeric strings. If you don&#x27;t have an issue with `add(a, b)` where `add` can be overloaded then there isn&#x27;t much rational basis for objecting to `a + b` where `+` can be overloaded.<br> <p> <font class="QuotedText">&gt; But once again the problem is the same: where is the compiler / linter flag that limits operator overloading to only &quot;sensible&quot; use cases? Where do you even draw that line?</font><br> <p> Sensible languages (such as Haskell) only allow overloading though the implementation of an interface (typeclass), which narrows the problem down: if you want to override `+` in Haskell then you need to provide an instance of `Num` for that data type, which implies that you need to implement the other numerical operations like `*`, `negate`, `fromInteger`, etc. which make up the minimal complete definition. If you try to define `+` at global scope outside of a `Num` instance without explicitly suppressing `Prelude.+` you&#x27;ll get an error due to the conflicting names.<br> <p> Typeclasses, in turn, generally come with &quot;laws&quot; which specify how their members should relate to each other, in addition to declaring types for each member which instances must share. (For historical reasons `Num` does not have any official typeclass laws itself, but there are certain basic expectations regarding associativity, commutivity, distributivity, and other properties[0] which amount to informal laws.) The laws, unlike the types, are not automatically enforced, but unlawful instances are strongly discouraged and it is usually simple to write property-based tests to verify that they are met. The key is that the instances of an interface are related by more than just a common name. Implementing a typeclass serves as a declaration of intent that the instance will follow the typeclass laws and generally behave as expected for an instance of that typeclass.<br> <p> It helps that Haskell allows almost any sequence of symbols as an operator name, so there is no pressure to abuse the left-shift operator for stream output. For example. You can also use any function name as an infix operator by putting it in backquotes—you can even define precedence and fixity for named functions used with infix syntax, just as you can for symbolic operators.<br> <p> Rust uses essentially the same model, with traits in place of typeclasses, though the set of numerical traits in Rust is a bit more nuanced than Haskell&#x27;s catch-all `Num` typeclass and the syntax unfortunately doesn&#x27;t allow for custom operators.<br> <p> [0] <a href="https://hackage.haskell.org/package/base-4.16.0.0/docs/GHC-Num.html">https://hackage.haskell.org/package/base-4.16.0.0/docs/GH...</a><br> </div> Thu, 03 Mar 2022 22:20:20 +0000 Moving the kernel to modern C https://lwn.net/Articles/886720/ https://lwn.net/Articles/886720/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; In response to the statement that sometimes a Phillips head screwdriver is useful? If you don&#x27;t believe that OO is useful for GUIs, point to alternatives and explain why OO languages are so popular for GUIs. KDE was done in C++ back before libstdc++ existed.</font><br> <p> Except that this article is not about GUIs. Maybe it should be - why do we keep on having to buy newer, faster computers just to stop the guis slowing everything down? Do we really want to let that bloat into the kernel - pretty much bringing our super-fast new CPUS to a grinding halt ...<br> <p> Cheers,<br> Wol<br> </div> Thu, 03 Mar 2022 22:19:33 +0000 Moving the kernel to modern C https://lwn.net/Articles/886714/ https://lwn.net/Articles/886714/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; But operator overloading and inheritance are very different: with them you don&#x27;t know _which source tab in your own editor you should look at_! In other words, you get lost in _your own code_.</font><br> <p> It&#x27;s easy to know where a + b comes from; if you know that a is of type Quaternion, then look in Quaternion.&quot;+&quot; or whatever the specific notation is. (If you were running Java, that would be in quaternion.java; in C, of course, even if you know the function name, it could be anywhere, so if you&#x27;re getting lost in your own code, you might want to look into Java or at least Java-like file naming conventions.) If you don&#x27;t know what type a is, you have bigger problems than operator overloading.<br> <p> Inheritance is more complex, yes. Ultimately, if it&#x27;s your own code, you should know what type is getting passed in and where to look for that code. Whether you&#x27;re using inheritance or switches, you&#x27;re going to need to know what the value is to see what code is being run, and if you know what that value is, you can find the code.<br> <p> <font class="QuotedText">&gt; But once again the problem is the same: where is the compiler / linter flag that limits operator overloading to only &quot;sensible&quot; use cases? </font><br> <p> You write in a language that has all code go through a general-purpose macro processor before the compiler, one that has long been shown to do evil, evil stuff (the Bourne shell being a notorious example of horrors that can be done by the well-intentioned.) You trust the programmer to be sensible, or (arguably) you run a more locked down language like Java.<br> <p> <font class="QuotedText">&gt; To a hammer, everything looks like a nail..</font><br> <p> In response to the statement that sometimes a Phillips head screwdriver is useful? If you don&#x27;t believe that OO is useful for GUIs, point to alternatives and explain why OO languages are so popular for GUIs. KDE was done in C++ back before libstdc++ existed.<br> <p> </div> Thu, 03 Mar 2022 19:05:58 +0000 Moving the kernel to modern C https://lwn.net/Articles/886645/ https://lwn.net/Articles/886645/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; (And as the IOCCC has shown over the years, #define is an awesome tool for code doing what you think it should do, not what the naive C programmer thinks it&#x27;s doing.)</font><br> <p> What you are *completely* missing, is that most code like you describe does NOT do what it NEEDS to do.<br> <p> For the application programmer (real or not), throwing hardware at the problem is an acceptable solution.<br> <p> For the systems programmer, you can&#x27;t just go out and get a couple of extra MEG of L1 cache. You can&#x27;t go out and get a couple of extra cache lines.<br> <p> I date from the years when tomorrow&#x27;s weather forecast took 20hrs to run. &quot;Who cares if the program takes twice as long?&quot; - that guy would have been fired!<br> <p> I did a load of work (copying files around, etc) a while back on my computer. Okay, I run a protection-heavy disk stack, but I think my PC spent the next 20 minutes flushing cache. I don&#x27;t give a monkeys, it was other wise idle and responsive, but there are PLENTY of people out there who HAVE to care.<br> <p> If you can optimise your code FOR SPEED without having a clue what&#x27;s going on under the bonnet, you&#x27;re a better man than I am, gunga din ...<br> <p> Cheers,<br> Wol<br> </div> Thu, 03 Mar 2022 08:50:36 +0000 Moving the kernel to modern C https://lwn.net/Articles/886631/ https://lwn.net/Articles/886631/ marcH <div class="FormattedComment"> <font class="QuotedText">&gt; Every step in computer history has reduced the programmer&#x27;s ability to know what code will run</font><br> <p> You&#x27;re mixing up operator overloading with totally unrelated things. Yes of course we have no idea what machine code runs, what micro code underneath that and of course with code-reuse (at last...) we don&#x27;t know what code runs in libraries. But operator overloading and inheritance are very different: with them you don&#x27;t know _which source tab in your own editor you should look at_! In other words, you get lost in _your own code_.<br> <p> That&#x27;s a huge difference. There is a very simple solution for all the rest: only use compilers and libraries versions that everyone else uses too. Not only it reduces the number of bugs massively, but when you hit one you can just google it. Not knowing which _code source_ runs in your own project is a totally different problem.<br> <p> <font class="QuotedText">&gt; a+b should add two items. If it&#x27;s not obvious what it&#x27;s doing, then that&#x27;s a bug in the library.</font><br> <p> I agree there&#x27;s only so much damage that can be done by overloading &#x27;+&#x27;. But once again the problem is the same: where is the compiler / linter flag that limits operator overloading to only &quot;sensible&quot; use cases? Where do you even draw that line?<br> <p> <font class="QuotedText">&gt; Java&#x27;s &quot;everything is a class&quot; is an annoying box, but when OO is useful, it&#x27;s really useful.</font><br> <p> To a hammer, everything looks like a nail..<br> <p> </div> Thu, 03 Mar 2022 03:22:05 +0000 Moving the kernel to modern C https://lwn.net/Articles/886622/ https://lwn.net/Articles/886622/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; Not knowing what code will run is considered a &quot;relatively minor thing&quot; only by fans of inheritance and object-oriented languages. </font><br> <p> Every step in computer history has reduced the programmer&#x27;s ability to know what code will run. As Mel, the Real Programmer, said when refusing to use assembly “You never know where it&#x27;s going to put things, so you&#x27;d have to use separate constants”. A C program that runs on *nix? The number of different compilers, processors, kernels and C libraries is amazing, the number of different combinations in practice at least runs into the thousands. If you&#x27;re using a library that you&#x27;re not bundling, that&#x27;s another source of change, and even if you are, have you read that library? <br> <p> (And as the IOCCC has shown over the years, #define is an awesome tool for code doing what you think it should do, not what the naive C programmer thinks it&#x27;s doing.)<br> <p> a+b should add two items. If it&#x27;s not obvious what it&#x27;s doing, then that&#x27;s a bug in the library. You can go with function names like cos, cosf, cosl, ccos, ccosf, ccosl (standard C adds type information to both sides of the function name, for all the mockery *nix programmers gave Hungarian notation), but I&#x27;d really rather not.<br> <p> <font class="QuotedText">&gt; good luck when troubleshooting some intermittent hardware bug or cache misconfiguration using &quot;printk&quot; over a slow serial link.</font><br> <p> I started to appreciate OO more when I read the argument that it succeeded because of GUIs, and I started to have to write some of those. If you&#x27;ve got a screen box that takes a bunch of GUI elements, I don&#x27;t know of any better way than making them all inherit from Widget, especially if you want to be able to add arbitrary widgets from arbitrary libraries. Java&#x27;s &quot;everything is a class&quot; is an annoying box, but when OO is useful, it&#x27;s really useful.<br> </div> Thu, 03 Mar 2022 02:11:28 +0000 Moving the kernel to modern C https://lwn.net/Articles/886618/ https://lwn.net/Articles/886618/ HenrikH <div class="FormattedComment"> Agreed that the implicit promotions and convert rules in C is a bit complex (and actually it would be nice if there where a tool one could use to highlight an expression and have the tool explain exactly what happens in this regard) but they are at least specified in the standard.<br> <p> For your example at hand with &quot;a + b&quot; where we have &quot;int a&quot; and &quot;unsigned int b&quot; and a have a negative value then since both are of the same rank (integers) but different types (signed vs unsigned) the signed integer is implicitly converted to an unsigned integer. Overflow is only undefined for the signed integer case while defined to wrap around for the unsigned integer which is why most of the &quot;a + b&quot; code works as intended.<br> <p> Aka if a is -1 and b is 2 then -1 is &quot;converted&quot; to 0xFFFFFFFF, add +2 and we wrap around to 1. In practice the compiler simply moves both a register and does the x86 ADD instruction since converting signed to unsigned of the same size is a no op and a binary add in particular is signedness agnostic.<br> </div> Thu, 03 Mar 2022 00:07:11 +0000 Moving the kernel to modern C https://lwn.net/Articles/886603/ https://lwn.net/Articles/886603/ marcH <div class="FormattedComment"> <font class="QuotedText">&gt; Not knowing what code will run is considered a &quot;relatively minor thing&quot; only by fans of inheritance and object-oriented languages. Even in C where OO is super-explicit, tracking what .ops will run is one of the most time consuming thing.</font><br> <p> Of course it&#x27;s not a problem at all for pure user space code that can run entirely in a graphical IDE with an excellent debugger. But good luck when troubleshooting some intermittent hardware bug or cache misconfiguration using &quot;printk&quot; over a slow serial link.<br> <p> <p> </div> Wed, 02 Mar 2022 18:55:32 +0000 Moving the kernel to modern C https://lwn.net/Articles/886595/ https://lwn.net/Articles/886595/ marcH <div class="FormattedComment"> <font class="QuotedText">&gt; &gt; That&#x27;s exactly why I despise operator overloading. You cannot trust anymore what you&#x27;re reading.</font><br> <p> <font class="QuotedText">&gt; It&#x27;s certainly an extreme reaction for a relatively minor thing. In an object orientated language, if your function gets passed a object x of type t, if t can be inherited from, x.method can do anything, no matter what the code for t says.</font><br> <p> Not knowing what code will run is considered a &quot;relatively minor thing&quot; only by fans of inheritance and object-oriented languages. Even in C where OO is super-explicit, tracking what .ops will run is one of the most time consuming thing.<br> <p> &quot;Object-oriented programming is an exceptionally bad idea which could only have originated in California.&quot; :-)<br> <p> And of course the classic http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html<br> <p> <font class="QuotedText">&gt; The King, consulting with the Sun God on the matter, has at times threatened to banish entirely all Verbs from the Kingdom of Java. If this should ever to come to pass, the inhabitants would surely need at least one Verb to do all the chores, and the King, who possesses a rather cruel sense of humor, has indicated that his choice would be most assuredly be &quot;execute&quot;.</font><br> <font class="QuotedText">&gt; The Verb &quot;execute&quot;, and its synonymous cousins &quot;run&quot;, &quot;start&quot;, &quot;go&quot;, &quot;justDoIt&quot;, &quot;makeItSo&quot;, and the like, can perform the work of any other Verb by replacing it with an appropriate Executioner and a call to execute(). Need to wait? Waiter.execute(). Brush your teeth? ToothBrusher(myTeeth).go(). Take out the garbage? TrashDisposalPlanExecutor.doIt(). No Verb is safe; all can be replaced by a Noun on the run.</font><br> <p> </div> Wed, 02 Mar 2022 18:19:36 +0000 Moving the kernel to modern C https://lwn.net/Articles/886529/ https://lwn.net/Articles/886529/ ianmcc <div class="FormattedComment"> You&#x27;ve got the history the wrong way around. The behaviour of C++ here hasn&#x27;t changed since it was first standardized in 1998. At that time, C didn&#x27;t allow a declaration in a for statement. C99 borrowed the wording from the C++ Annotated Reference Manual, without realizing that the wording had been updated during the C++ standardization process. So C introduced an incompatibility with C++, not the other way around. The C standards committee documents are very clear that this was accidental, not intentional.<br> <p> The bottom line is that C++ will flag an error in some instances of very dubious code that is most likely a bug anyway (i.e. declaring a variable that shadows the loop control variable) where C99 would allow it. None of the standards committee see it as something worth the bother of fixing. If you really did intend to introduce a shadow declaration, the simple fix is to enclose it in another compound statement.<br> <p> </div> Wed, 02 Mar 2022 08:56:25 +0000 Moving the kernel to modern C https://lwn.net/Articles/886433/ https://lwn.net/Articles/886433/ dvdeug <div class="FormattedComment"> <font class="QuotedText">&gt; That&#x27;s exactly why I despise operator overloading. You cannot trust anymore what you&#x27;re reading.</font><br> <p> It&#x27;s certainly an extreme reaction for a relatively minor thing. In an object orientated language, if your function gets passed a object x of type t, if t can be inherited from, x.method can do anything, no matter what the code for t says.<br> <p> Even in C, a + b can do quite a few different things. Off the top of my head, I can&#x27;t tell you what happens if a is a signed int with a negative value and b is an unsigned int. I do recall that integer overflow is undefined behavior, which is all sorts of fun. If you know the underlying types and the type programmer was sane, extending + to new types shouldn&#x27;t make things much more complex.<br> </div> Tue, 01 Mar 2022 23:32:51 +0000