I've never had to do any kernal programming, so I don't understand what
the relevant restrictions are, or why they exist. What is problematic
about local static variables? They're not specific to C++, so I assume
that the following C code would also be problematic?:
Sorry - let me be more clear. In an environment you completely control,
adding 'runtime support' for global c/dtors and local static variables
is quite easy (See
http://wiki.osdev.org/C++ ). My issue, in this case,
with them is that I cant think of a way of a Linux kernel module adding
its own runtime support (other than bypassing the Kbuild system and
attempting to link it up yourself)
int save_val(int i)
{
static int saved;
int retval = saved;
saved = i;
return retval;
}
There is a difference between how GCC and G++ treat static local
variables. G++ generates extra code to put a mutex around it to prevent
concurrent initialisation, and this is what requires the runtime
support. (Admittedly this is only G++. Other C++ compilers wont, but
best of luck to you trying to compile even the kernel header files
The built-in C types fall into a number of categories, based upon which
operators work on them: arithmetic types, pointer types, array types,
functions. Operator overloads work best when they make something that is
of class type work like a member of one of those categories: extended
numeric types such as quaternions or arrays, smart pointers, containers,
or function objects.
And this is all perfectly reasonable in userspace, but not in kernel
space. Floating point calculations are to be avoided at almost any
cost, because they are not useful in the vast majority of cases, and
incur extra overhead if the kernel needs to save/restore its own
floating point state as well as that of the tasks it is scheduling.
...They only lead to confusion when used for other
purposes. I don't imagine there's much need for extended arithmetic
types in kernal programming. However, it seems to me that various kinds
of smart pointers or containers could be useful, unless they can't be
properly implemented. If there's any place where kernel code passes
around function pointers, passing around function objects might be a
reasonable alternative.
What form of smart pointers? I assume you mean shared_ptr. They are
just a pointer and a reference count. In the C++ world, the refcount
lives with the pointer, while in the kernel, objects needing refcounting
have a ref count in them. The C world has better locality of data in
the cache, while the C++ world also suffers from the same indirection
problem as function pointer objects.
Lets consider the difference between passing a function pointer in C
(which fits in a register, or single word on the stack), with passing a
C++ function pointer object. The C++ function pointer object is
necessarily as large.
How about calling this function pointer? In C, you would load it off
the stack, or from ram, into a register, and 'call's the address in the
register. In C++, you grab a pointer to the function pointer object,
pass it to the operator() function for your object, which deferences the
pointer, finds the function pointer member variable, loads this into a
register and 'call's the address in the register.
So yes - both of these will indeed work, but see the difference between
working and working and working well. One of the worst things a kernel
can do is needlessly follow pointers, as this takes more time, and leads
to cache misses. The C way of doing things results in less memory
overhead, (both in terms of code size and data size), involves fewer
pointers to follow, and has better cache locality.
The point of having a template is that you have code that needs to be
duplicated, depending upon the template's parameters. Properly used, you
shouldn't be able to avoid the duplication by using C (or the C subset
of C++). If there's code that wouldn't have to be duplicated if you were
using C, then in C++ that code should be factored outside of the template.
Of course, not everything that should be done, is done - I've seen that
a lot in C, and now that I've working on a C++ project, I'm seeing the
same thing in C++. But that's due to misuse of templates, not because of
templates themselves.
Agreed, subject to your statement of "Properly used". However, I cant
think of a single case where templates would be useful.
If you can construct an object in C without much work, you can write C++
code that requires no more work than the C code to construct it; it
will, in general, be the same (or almost the same) code. The only reason
why C++ construction gets more complicated is if you want to make use of
a C++ feature not supported by C, and if you're sane, you only do that
if that feature provides some benefit that justifies the extra work. I
don't see that as justifying an avoidance of C++.
It's only meaningful to compare optimization of equivalent code. C
doesn't support virtual function calls; the closest equivalent is C
requires use of a function pointer. Can a typical C compiler do any
better of a job inlining calls through function pointers than a C++
compiler can do of inlining virtual function calls?
Ok - fair points. As with templates, I cant think of a useful use case
for compound objects. From a naive point of view, virtual functions via
an interface design model could seem very attractive and useful in a
kernel environment. However, a virtual function call is 2 pointers to
follow rather than one, going back to the performance aspect.
The point I was trying to get across is that C++ opens up a whole
toolkit of new and shiny features which are not needed and when used
with the best of intentions lead to poor performance. This alone is the
biggest reason why I believe C++ should not be used.