Oh fine, but if you are going to post Microsoftās quasi official position on
this, it should be qualified by the fact that concurrent to the release of
this white paper, Microsoft was developing a C++ based object oriented
driver framework, subsequently released as KMDF. Goose, gander.
On Jan 25, 2008 4:52 AM, amitr0 wrote:
> lots have been already said and done with this thread. But on one gave the
> ārealā answers. while it is true that the poster whud read older postings
> before submitting, we shud appreciate tht electronic searches still depend
> on search strings and might not always reveal thebest results. any how, i
> simply googled, and here is a copy paste from what i foundā¦hope this
> helpsā¦
>
> C++ Issues for Kernel-Mode Drivers
>
> Microsoft developers have discovered a number of areas where C++ presents
> particular problems for kernel-mode drivers.
>
> Code in Memory
> The most severe problem with using C++ for writing kernel-mode drivers is
> the management of memory pages, particularly code in memory, rather than
> data. It is important that large drivers be pageable, and paged code is not
> always in memory. All of the code that will be needed must be resident
> before the system enters a state in which paging cannot occur.
>
> The way the C++ compiler generates code for non-POD classes and templates
> makes it particularly difficult to know where all the code required to
> execute a function might go and thus difficult to make the code safely
> pageable. The compiler automatically generates code for at least the
> following objects. These objects are put āout of line,ā and the developer
> has no direct control over the section in which they are inserted, which
> means they could happen to be paged out when needed.
>
> ?
>
> Compiler-generated code such as constructors, destructors, casts, and
> assignment operators. (These can often be explicitly provided, but it
> requires taking care to recognize that they need to be provided.)
>
> ?
>
> Adjustor thunks, used to convert between various classes in a hierarchy.
>
> ?
>
> Virtual function thunks, used to implement calls to virtual function.
>
> ?
>
> Virtual function table thunks, used to manage base classes and
> polymorphism.
>
> ?
>
> Template code bodies, which are emitted at first use unless explicitly
> instantiated.
>
> ?
>
> The virtual function tables themselves.
>
> The C++ compiler does not provide mechanisms for direct control of where
> these entities are placed in memory. The pragmas necessary to control memory
> placement were not designed with C++ in mind. #pragma alloc_text cannot be
> used to control the location of a member function because (for several
> reasons) there is no way to name the member function. The scope of #pragma
> code_seg is ambiguous for compiler-generated functions, expanded template
> bodies, and compiler-generated thunks. There is no mechanism at all for
> controlling the location of virtual function tables, since they are not
> quite either code or data from the point of view of the compiler (they go
> into a section all their own).
>
> If a function in a header is declared inline, but the compiler does not
> generate inline code for it, the function may be emitted in more than one
> code segment depending on where the function is used. When a class template
> is instantiated, it is generated in the section that is current at the point
> of first use, and it is not always immediately obvious which section that
> is. Both of these issues can lead to code being pageable when it should not
> be, or vice versa.
>
> If a class hierarchy is in use, whether code for a base class needs to be
> in memory when the derived class is accessed depends on exactly which
> functions in the base class are called from the derived class (and whether
> the compiler can inline them), as well as what sections they were emitted
> in. For example, if the derived class provides a method that uses no base
> class methods, the base class code need not be in memory. However, it is
> difficult to know when that is the case. Additionally, any thunks used with
> the hierarchy and its classes might also need to be resident in memory.
>
> Stack
> The compiler has always been free to generate additional data on the
> stack, such as creating temporary objects, deferring call cleanup, and other
> actions that use the stack in a hidden fashion. There are few differences
> between C and C++ with respect to the way a single function uses the stack,
> but because of the additional mechanisms that usually result in more
> function calls, C++ will often use more total stack. You should keep stack
> size in mind, as you would in any programming language when stack space is
> limited.
>
> Exceptions also have an effect on the stack. See āExceptions and RTTIā
> later in this paper.
>
> Dynamic Memory
> Driver development tools such as Driver Verifier rely on tagged memory to
> validate memory usage in drivers. Using operator new and operator
> delete to allocate and free memory weakens the ability of these tools to
> detect memory leaks and other problems in driver code.
>
> In user space,* operator new* and operator delete are convenient, but
> they can become cumbersome in drivers that use multiple memory pools or
> tagged memory. Because āplacement newā takes additional operands, it is
> possible to pass in the information needed to select memory pools or
> generate tags into an overloaded operator new , but this is not much
> easier than using the memory functions directly. Because there is no
> āplacement deleteā with additional arguments to pass in a tag or a pooltype,
> there is no way to pass in a tag (or memory control, if needed) when using
> operatordelete, making it impossible to check that the tag at the point
> of release was the intended one, thus defeating much of the benefit of using
> tagged memory. It is possible to delete memory without providing a tag,
> but in each case you will need to decide whether the risks and disadvantages
> of not using tags in driver code overcome the apparent convenience.
>
> Memory tracing tools often record the return address of the function that
> made an allocation. Some C++ compilers implement operator new as a
> function, causing all allocations to appear to come from a single location
> and defeating the purpose of that aspect of the memory tracing tool. This
> can be addressed, but you will have to determine for yourself if there is a
> benefit in doing so over using memory allocation directly.
>
> Libraries
> There are a number of distinct concerns in creating and using libraries:
>
> ?
>
> The name of exported C++ functions can vary from one release to another.
>
> ?
>
> Not all of the functions available in user mode are available in the
> kernel-mode libraries.
>
> ?
>
> The Standard Template Library is designed to work with data objects from a
> single DLL.
>
> C++ functions are exported based on their entire signature, not on their
> name alone (as C functions are). The name of a C++ function is āmangledā to
> contain type information, which becomes part of its signature. Although the
> rules for name mangling are fairly stable, there is no guarantee that the
> mangled names will be the same from release to release of the compiler.
> Therefore, C++ functions cannot be reliably exported to a library from one
> release to the next, although functions that can be represented as extern
> āCā functions can. In addition, the use of a .def file can help mitigate
> the problem. Note that extern āCā functions are unique only on the basis
> of name, not the entire signature as in C++.
>
> Not all library functions are available in kernel mode, particularly those
> associated with the āadvancedā C++ language features. The Standard Template
> Library is the āusualā way to implement many C++ concepts such as variably
> sized arrays. However, it is unsafe to simply assume that the Standard
> Template Library is present and usable. Although much of the Standard
> Template Library is implemented as source code in headers, it occasionally
> uses library functions or other features that are not available or usable in
> the kernel environment.
>
> The Standard Template Library is also based on the assumption that each
> data object it uses exists in only a single DLL. Although in most cases it
> works to pass references to POD objects across DLL boundaries, passing
> references to more complex structures such as lists may cause runtime
> failures that can be hard to diagnose. Known issues include the fact that
> freeing memory in a DLL other than the one in which the memory was allocated
> can cause failures (at least for debug-mode compiles) and that the āend of
> listā marker differs between DLLs, which can cause unexpected runaway list
> searches. You must be aware of these problems and take steps to prevent
> them.
>
> We do not recommend using Standard Template Library functions in a
> kernel-mode driver, because it is not possible to assume that the Standard
> Template Library is there and ājust works.ā In the case of kernel-mode code,
> understanding precisely how a particular data structure is implemented helps
> assure that it does not violate the requirements of kernel space. It is also
> possible that a specialized implementation will be smaller than the more
> general Standard Template Library functions, although the library is often
> very good in that regard.
>
> Exceptions and RTTI
> It is tempting to use C++ exceptions, but they are difficult to implement
> in kernel mode. C++ exceptions require a kernel-mode-safe library, which
> does not currently exist. They also present an unavoidable runtime problem,
> because exception records that are generated when an exception is thrown are
> large objects on the very limited stack. On x86 systems, exception records
> are not particularly large (although they are large compared with many
> typical stack frames), but on Intel Itanium systems they are quite large: 3K
> to 4K, or one-sixth to one-eighth of the available 24K stack space. To
> preserve portability of a driver to 64-bit platforms, exceptions would have
> to be used in a very limited way, even on the x86 architecture. The
> rethrow operator can cause multiple exception records on the stack. Note
> that Structured Exception Handling (* try* /* except*/__finally) is
> available in kernel mode, although the space concerns remain. C++ exceptions
> have a number of semantic subtleties that prevent them from simply mapping
> onto Structured Exception Handling.
>
> Run-time type information (RTTI) also requires a library that does not
> currently exist for C++ in kernel mode. So far, there have been few, if any,
> requests for this in kernel-mode code. Whether this lack of demand is a
> consequence of the other problems masking it or because it is not useful in
> kernel mode is unknown.
>
> Compiler Versions
> Although the C++ language standard is stable, implementation techniques
> are still evolving. Consequently, compiler versions may change the way
> generated code operates. Such changes are unlikely to affect user-mode code,
> but they can affect kernel-mode code in which more of the underlying
> implementation is exposed to (and sometimes provided by) driver developers;
> version-to-version interoperability of kernel-mode code is not guaranteed.
>
> You should carefully control any interface between two drivers or a driver
> and the operating system, usually by writing the interface in C instead of
> C++. Otherwise, version-to-version incompatibilities in the C++
> implementation may cause interoperability failures.
>
> Static and Global Scope Variables and Initialization
> C++ static variables (declared at either global or local scope) present a
> number of problems for drivers.
>
> The C++ standard allows static variables declared at local scope to be
> initialized at the time of first use (the first time the scope is entered).
> The way this is implemented both creates the possibility of race conditions
> during initialization and a particularly high risk of unintended data
> sharing between threads, because variables declared static are globally
> static, not per-thread. For globally static data (shared among threads) it
> is best to do it explicitly at global scope, to make sure access protections
> appropriate to the situation are applied.
>
> If a C++ global object requires initialization (a global constructor) is
> declared, there is no mechanism for the constructor to be called. Global
> objects that require constructors should either not be used, or you must
> develop a mechanism to assure that the constructor is called. Several
> sources on the Web claim to have solved this problem, and one of those
> solutions might work for you.
>
> The order of initialization of global objects is not specified by the C++
> standard, so even if there were a mechanism to call their constructors,
> either the order of initialization must be explicitly controlled by the
> driver code, or it must not matter.
>
>
> On Jan 25, 2008 3:12 PM, wrote:
>
> > Reinhard,
> >
> > > the problem is that many people on this list donāt want to see the
> > same
> > > arguments again and again
> >
> > Sure. This is why, in my opinion, it makes sense to isolate these
> > arguments on some separate thread(s) that will be completely ignored by the
> > vast majority of readersā¦
> >
> > > Of couse nobody must read the read. But what is it worth then?
> >
> > Well, even if thread is of no interest to overwhelming majority of list
> > readers (letās say 95%),
> > it is still of interest to the remaining 5% (because otherwise no one
> > would post to it, in the first place, so that it would just die in itself).
> > This NG has more than 50K subscribers, which, if we assume 95% vs 5% ratio,
> > still gives us 2 500 potential readers. You donāt really want to deny them
> > a chance to discuss a topic that is of interest to them, do you (please
> > note that I am not among them - Iāve got no interest in C vs C++ topic
> > whatsoever). If you do ⦠then think again - if they have no chance to
> > do it here, they will be just raising this issue on other threads,
> > effectively hijacking them. Just to give you an idea, in the last 2 weeks I
> > saw C vs C++ discussion on 3 threads that I have participated inā¦
> >
> > Anton Bassov
> >
> > ā
> > NTDEV is sponsored by OSR
> >
> > For our schedule of WDF, WDM, debugging and other seminars visit:
> > http://www.osr.com/seminars
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> > http://www.osronline.com/page.cfm?name=ListServer
> >
>
>
>
> ā
>
> - amitr0 ā NTDEV is sponsored by OSR For our schedule of WDF, WDM,
> debugging and other seminars visit: http://www.osr.com/seminars To
> unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
ā
Mark Roddy