> object orientation isn't a language feature; it's a programmer feature
That's like saying "as long as it's possible to put nails into the wall by hand, why using a hammer?".
A language has to support common and daily tasks to be done by programmers. The kernel is full of object oriented designs like inheritance, virtual functios, namespaces, inline functions, member functions, member access, etc., why not using a hammer?
Of course, I also know people and designs who try to do every thing object oriented, drawing bubbles around everything they can find, and the connecting them via funny lines with arrows and bars. That's not the way I'd like to see C++ in the kernel, more the way I use it since g++ supports C++ and we were using C++ for embedded designs a lot, even down to standalone code in very fast boards e.g. inside FlexRay data loggers. No new/delete from libc++ but own implementations, no artificial inheritance or virtual functions with pointer arrays, simple and readable code, not overdoing it.
Posted Jan 13, 2011 13:50 UTC (Thu) by khim (subscriber, #9252)
[Link]
The kernel is full of object oriented designs like inheritance, virtual functios, namespaces, inline functions, member functions, member access, etc., why not using a hammer?
Because not everything is a nail? Seriously: take a look on how kernel does thing and you'll see that C++ design will be more complex and much less flexible. C++ is great hammer but it's still a hammer. If you use C++ then you tend to think that every problem is a nail and this leads to truly ugly code.
Today's C++ (especially C++ 200x in GCC 4.5+) includes more then hammer, but it's still quite hard to use right (and the code produced in C++ is usually significantly more resource-hungry and slower then code written in C), but 10 years ago it was a joke.
I think it's good idea to use C++ for things where there are not enough developers ("bloated and slow, yet working program" is still better then lead and mean program which "will be delivered RSN for the last 10 years"), but for kernel C++ is bad choice.
Not everything is a nail...
Posted Jan 14, 2011 4:55 UTC (Fri) by HelloWorld (guest, #56129)
[Link]
Because not everything is a nail? Seriously: take a look on how kernel does thing and you'll see that C++ design will be more complex and much less flexible. If you use C++ then you tend to think that every problem is a nail and this leads to truly ugly code.
Everything that can be done in C can be done at least as well in C++. Claiming that C++ would have led to a more complex and less flexible design is thus downright absurd. C++ is a multi-paradigm language that doesn't force any particular programming style down anybody's throat, and if doing things like in C provides advantages, C++ won't stop you.
(and the code produced in C++ is usually significantly more resource-hungry and slower then code written in C)
That's outright bullshit. A key design decision in C++ has always been "don't pay for what you don't use", and it worked out pretty well in fact.
Not everything is a nail...
Posted Jan 14, 2011 9:43 UTC (Fri) by dwmw2 (subscriber, #2063)
[Link]
The problem in the kernel is that we get a lot of drive-by contributions from people who don't really know what they're doing. A lot of driver code is pure crap.
You are absolutely right that C++ can be used sparingly. Qt handles it fairly well, enforcing a sane use of a subset of C++ rather than the whole range of features.
However, this does depend on restraint on the part of the developers. If we had C++ available, we would either spend a lot of time telling developers "no, you can't do that", or we'd accept a lot of use of C++ features that we would prefer not to use.
It is often the case that certain developers don't have a full understanding of the cost of the code they're writing, even when they're using C. Not everyone is forced to spent part of their life looking at the compiler output from their code and seeing what it actually does, although they ought to be.
While the "don't pay for what you don't use" principle has indeed worked out pretty well in general, the fact remains that people would be using more, and thus paying more. Unless you just want us to compile our existing C code with a C++ compiler? :) Which wouldn't work today because we make heavy use of C99 structure initialisation, and I don't believe that works in C++?
Not everything is a nail...
Posted Jan 21, 2011 15:56 UTC (Fri) by daglwn (subscriber, #65432)
[Link]
It is often the case that certain developers don't have a full understanding of the maintenance cost of the code they're writing,
I am sick and tired of kernel people spouting ignorance about C++. They look like fools. Every single project I've followed that places restrictions on the use of C++ ends up with bugs and misdesigns that could have been avoided had the leadership opened its minds to the idea that C++ is a cohesive language. Stripping parts of it out just means you're throwing away safety, code reuse or both.
Not everything is a nail...
Posted Jan 21, 2011 20:31 UTC (Fri) by xilun (subscriber, #50638)
[Link]
And only work with C++ experts in any cases (restrictions or not). Who are even more difficult to find than C experts, and C experts are already difficult enough to find...
Not everything is a nail...
Posted Jan 21, 2011 23:41 UTC (Fri) by daglwn (subscriber, #65432)
[Link]
I really question whether competent C++ developers are hard to find. There are lots of C++ jobs out there so it's not as if the language isn't being used. You really have to try _not_ to learn something about a language after using it for a while.
In my experience the problem is resistance to the unknown, no matter how much that unknown might improve one's productivity.
Not everything is a nail...
Posted Jan 21, 2011 21:46 UTC (Fri) by Spudd86 (guest, #51683)
[Link]
The problem is that many C++ features would need additional support code that doesn't currently exist in the kernel (for example, exception handling with zero overhead in the case of no exceptions thrown would need both new kernel code to support it and tighter coupling between the kernel and compiler).
In the kernel restrictions are more than just style or taste, they are also because the user space code that the compiler relies on being present in the final executable may not work in kernel space, if it doesn't that feature either cannot be used or replacement support code must be written, the latter option ties the kernel more tightly to the compiler and increases the chances that a new compiler version will break the kernel.
Not everything is a nail...
Posted Jan 21, 2011 23:52 UTC (Fri) by daglwn (subscriber, #65432)
[Link]
Of course something like exceptions would require support code in the kernel and I'm not advocating that exceptions are necessarily the best way to do error handling in the kernel. I'm not an expert in the kernel domain so I don't feel qualified to judge either way. The same goes for rtti, which can often be avoided anyway.
What I am advocating is that the kernel people unplug their ears, uncover their eyes and think about what benefits C++ might bring. It would help tremendously with writing code that uses callbacks. The whole filesystem architecture with the VFS layer and implementation layers is crying out for an inheritance model. RAII would help a lot with resource cleanup.
Heck, RAII *alone* should be enough to seriously consider C++ in any project.
Now rewriting the filesystem architecture is too much to expect (I'm just giving it as a well-known example) but these kinds of patterns abound in most code. C++ really can save a lot of lines of code and that usually means fewer bugs and often better performance.
But the trick is, you have to use the multi-paradigm features of the language. Multiple inheritance, templates, operator overloading and constructors/destructors complement each other in surprisingly beautiful ways. I have heard strong arguments against all of those features and I just shake my head in sadness every time I have to address them.
Not everything is a nail...
Posted Jan 22, 2011 0:52 UTC (Sat) by jmm82 (guest, #59425)
[Link]
The VFS already has an inheritance model in c, it is called function pointers.
Not everything is a nail...
Posted Jan 22, 2011 1:25 UTC (Sat) by daglwn (subscriber, #65432)
[Link]
Which is, of course, my whole point. Why go through the pain and bugs involved with function pointers when the compiler will generate it for you? It baffles me why anyone who advocates using tools to automate tasks (i.e. anyone who writes code) would abandon that principe at some arbitrary level of the development stack.
Not everything is a nail...
Posted Jan 25, 2011 9:38 UTC (Tue) by paulj (subscriber, #341)
[Link]
You can do RAII in C just fine...
Not everything is a nail...
Posted Jan 25, 2011 16:06 UTC (Tue) by jrn (subscriber, #64214)
[Link]
I suppose it depends what RAII means. But no, I am not aware of a simple way to, say, free memory on the heap when a pointer to it falls out of scope (especially when a "return" statement exits that scope).
Not everything is a nail...
Posted Jan 25, 2011 16:41 UTC (Tue) by etienne (subscriber, #25256)
[Link]
Maybe you do not have the problem of freeing memory when a local structure goes out of scope in C (outside of kernel space), because in that case the local structure is declared in the stack and will be freed automatically...
Maybe the real problem is that your "autoptr" is not able to manage an object in the stack, but you need an "autoptr" because one method has such an argument.
Not everything is a nail...
Posted Jan 25, 2011 22:18 UTC (Tue) by daglwn (subscriber, #65432)
[Link]
Will that local structure also close files for me when it goes out of scope? Or does that local structure free memory pointed to by members of that structure when it goes out of scope? Or does that local structure release a lock it holds when it goes out of scope?
RAII is about MUCH more than memory.
Not everything is a nail...
Posted Jan 26, 2011 12:32 UTC (Wed) by paulj (subscriber, #341)
[Link]
For me RAII in the abstract is an object/resource-lifetime management strategy, such that creation and destruction of composite objects appear atomic wrt resources/objects held internally, as far as users of the object are concerned. Obviously it's good programming to try make objects atomic in this way when designing code.
C++ has implicit calls to constructors and destructors, which tie in to scoping. C doesn't have that, true, and requires explicit construction and destruction (you can still hide destruction behind refcounting, obv). It's often bad practice and/or a sign of a (quick)? hack when C code uses automatic allocating for non-trivial, composite objects.
Whether language support for implicit ctor/dtors tied with scoping is required for a practice to be called RAII, I don't know. I guess to a C++ person it does. Still, the general sentiment of RAII seems more widely applicable than C++.
Not everything is a nail...
Posted Jan 26, 2011 19:52 UTC (Wed) by daglwn (subscriber, #65432)
[Link]
Implicit destruction (finalization, uninit or whatever you want to call it) seems to me integrally tied to the concept of RAII. Without it, one ends up having to cover all exit points of a scope with explicit calls to cleanup code. Either this means there are several such calls scattered around parts of the enclosing scope or there's a big ugly goto to a common piece of cleanup code. Neither is particularly attractive or maintainable.
This gets to be impossible if the exit points are not known statically. C++ exceptions are a classic example but since some seem to think the C++ exception model is broken, I will emphasize that the problem is NOT solved by eliminating exceptions. One still has to cover all exit points with cleanup code.
Perhaps a better term for this would have been "resource ownership is object lifetime."
Not everything is a nail...
Posted Jan 30, 2011 0:37 UTC (Sun) by nix (subscriber, #2304)
[Link]
*Closures* would help tremendously in writing code that uses callbacks. But they require quite a lot of runtime support which is not available in the kernel.
C++'s syntactic sugar is insignificant in comparison. (At least, in this area. I agree that RAII is really nice, but the kernel seems to be surviving without it.)
Well, it's quite simple, really...
Posted Jan 18, 2011 11:34 UTC (Tue) by khim (subscriber, #9252)
[Link]
Everything that can be done in C can be done at least as well in C++.
Well, this is strawman argument: of course you can just ignore all C++ extensions and then produce the same code in C++ as in C. But what's the point? If you try to use "real" C++ facilities...
$ cat hello.c
#include <stdio.h>
int hello() {
printf("Hello, World!\n");
}
$ gcc -O3 -c hello.c ; size hello.o
text data bss dec hex filename
72 0 0 72 48 hello.o
$ cat hello.C
#include <iostream>
int hello() {
std::cout << "Hello, World!" << std::endl;
}
khim@khim-glaptop:/tmp$ gcc -O3 -c hello.C ; size hello.o
text data bss dec hex filename
244 8 1 253 fd hello.o
Claiming that C++ would have led to a more complex and less flexible design is thus downright absurd.
Not really. Most C++ designs are indeed more flexible, but this is not a big factor for kernel development where you can always redesign anything (the infamous "stable API nonsense"), but the fact that they are "more flexible" usually means they are more complex and less efficient.
(and the code produced in C++ is usually significantly more resource-hungry and slower then code written in C)
That's outright bullshit. A key design decision in C++ has always been "don't pay for what you don't use", and it worked out pretty well in fact.
Where "pretty well" == "bloat of about factor of two or three". Yup. C++ does not impose choice on your so you end up with 4-5 implementations for basic things. Heck, C++ standard includes two different string implementations from the start (I mean "char *" and "std::string") - and different libraries like to add additional ones! And we are talking about kernel, remember? Kernel shares L1 with userspace program and it's pitiful: 64K at most. And, please, don't talk about Moore's Law here: PowerPC 601 had 32K cache 18 years ago, Intel Core2 has 32K cache today. Yeah, it's kind of "apples vs oranges" because there are two 32K caches on Core2 and PowerPC 601 and AMD's Phenom has whopping 64K L1 cache, but anyway: even two doublings per 18 years is not enough to claim that endless adapters and transformers are no longer meaningful for kernel.
The "don't pay for what you don't use" is only good when you don't use anything. When you actually do use some facilities you suddenly find out that they cost more then in case where language imposes things on you.
Well, it's quite simple, really...
Posted Jan 18, 2011 12:08 UTC (Tue) by dwmw2 (subscriber, #2063)
[Link]
"Well, this is strawman argument: of course you can just ignore all C++ extensions and then produce the same code in C++ as in C."
Can I? In the kernel we make heavy use of C99 structure initialisation. Where structures can so often change and gain new members, it's very important to have named initialisers. But this code will fail if compiled as C++:
struct foo {
int a;
int oh_we_introduced_this_optional_thing_later;
int b;
};
struct foo f = {
.a = 1,
.b = 2,
};
Losing that facility would introduce a lot of errors into the kernel, at a single fell stroke.
Well, it's quite simple, really...
Posted Jan 18, 2011 13:27 UTC (Tue) by foom (subscriber, #14868)
[Link]
Surprisingly, it didn't even make it into C++0x.
It seems to me it'd be a reasonable extension for "gnu++0x", though.
Well, it's quite simple, really...
Posted Jan 18, 2011 18:57 UTC (Tue) by daniel (subscriber, #3181)
[Link]
The lack of designated initializers in C++ is pure brain damage. I do not understand why the issue does not get more attention. That said, the old gnu syntax still works: {foo: x, bar: y} except that you have to specify the initializers in the order declared and insert nulls if you skip fields, the latter requirement serving no imaginable purpose whatsoever. But at least in this way you can protect yourself from structure field evolution. This C advantage in no way makes up for all the structuring primitives that C lacks.
Well, it's quite simple, really...
Posted Jan 18, 2011 21:07 UTC (Tue) by foom (subscriber, #14868)
[Link]
It doesn't sound like brain damage, but rather a brand new (well, 12 years old now, but by C standards, brand new) feature in C that has not been ported to C++ yet. C++ adds all sorts of additional complex interactions to such a feature that would have to be properly specified...and nobody's done that yet. You could probably get a proposal accepted for C++20 (or whatever) though...
The restrictions on the GCC extension seem like someone just didn't really finish implementing it yet. I'd bet you would be welcome to do so.