Placement new operator in a driver

“Edouard A.” wrote in message
news:xxxxx@ntdev…
> What matters is what tool is right for you. If you prefer C, by all
> means
> use it.

Sorry it is not what is the right tool for you, it is the right tool for
your customer. Almost all of us work for someone directly or indirectly,
the responsible professional will address the customers needs. If the firm
has a lot of toolX experience and is likely to keep a continuing staff with
experience in the kernel in toolX then consider using toolX. But if toolX
is outside of the Microsoft driver development norm, think of all the
challenges:

1. If you are one of the first employees for Windows kernel
development, is toolX something that is going to be easy to hire people with
experience in using it for Windows drivers?

2. If this is a contract, or a short time put together a team for a
specific goal, how is a customer going to deal in the future when they need
a bug fix for something based on toolX? This could mean a lot of studying,
or even a rewrite if there is a problem and you are gone.

3. The hardest to qualify: is toolX likely to give a benefit of a high
enough multiplier to justify the risk? I typically look for a 2 times
multiplier as the lowest to consider for a using a product outside the norm.
This multiplier needs to be thought of for the first 2 years or more of the
product shipments, not just development.

Now you can replace the term toolX with C++, a third party toolkit, or
something else. I don’t count Microsoft efforts such as KMDF, UMDF,
mini-filters, WMI libraries, etc in this. The Microsoft efforts are going
to go mainstream, and the people resources will be there in the future.

A good professional will consider the questions above (and others I’m sure
people can offer) before using toolX whatever it will be. We should be
doing our best for our customers and the end users, a particular technology
is a secondary (or lower) consideration.

As a consultant I have had to tell customers the best thing they could do is
throw out the tool and the code (and in one instance the development team).
This is not something anyone wants, but using a toolX can cause this to
happen. This is why one should look carefully before going outside the
Microsoft guidelines, the company and job you save by avoiding “something
special” could be your own.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Remove StopSpam from the email to reply

Any progress convincing the compiler folks to fix this problem?

=====================
Mark Roddy DDK MVP
Windows 2003/XP/2000 Consulting
Hollis Technology Solutions 603-321-1032
www.hollistech.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Saturday, April 22, 2006 1:14 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

You can get 1) and 2) just by using a .cpp file and then using C BTW.
/W4 also gets you most of the way in C.

> However I came accross a memory optimization problem, when I add an
object my template does something like :

Please tell me you are not using templates. If you are don’t
try to make any function pageable, otherwise the linker may
place templacized code in the wrong segment.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Edouard A.
Sent: Saturday, April 22, 2006 8:24 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

The reason why I use C++ instead of plain C are :

  • Strict type checking;
  • In place declaration of variables;
  • Object-oriented programming (although you have to be
    cautious with what you use).

However C++ will not make your driver better or worse than if
written in C, because the only real influence on software
quality is the person behind the keyboard.

Anyways, after reading what Loren said I think I should write
a driver in pure assembly and hand over maintenance to a newbie. :stuck_out_tongue:

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of MM
Sent: Saturday, April 22, 2006 15:04
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Placement new operator in a driver

Curious, but what is the purpose of C++ in a driver? Other
than added problems such as this, why?

Sorry, couldn’t resist sparking this one again… But
really, all of this can be done in C, so what’s the point in
using C++ where there will be added problems/hassles?

Driver Works is proof drivers shouldn’t be written in C++ (of
all their developers and dollars, they never got it right).

Well, my gas can is now empty - I’m sure I’ll have some
interesting reading later… :slight_smile:

m.

Jan Bottorff wrote:

>Can you tell us EXACTLY what error you get?
>
>- Jan
>
>
>
>
>>Yes I did, that’s what I don’t undestand.
>>
>>The operator profile is something like this :
>>
>>class CMyBaseClassWithOperatorSomething { //…
>> // with placement
>> void *operator new(size_t lSize, void *pBuffer);
>> // without placement
>> void *operator new(size_t lSize);
>>//…
>>};
>>
>>Perhaps a typo somewhere, I shouldn’t minimize the impact of my own
>>stupidity. :wink:
>>
>>
>
>
>
>—
>Questions? First check the Kernel Driver FAQ at
>http://www.osronline.com/article.cfm?id=256
>
>To unsubscribe, visit the List Server section of OSR Online at
>http://www.osronline.com/page.cfm?name=ListServer
>
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer




Wanadoo vous informe que cet e-mail a ete controle par
l’anti-virus mail.
Aucun virus connu a ce jour par nos services n’a ete detecte.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer

Worse, if you look at a KMDF stack it is obviously a C++ design with a C API
wrapper. However I also tend to hate smart pointers. I suspect my loathing
is however not quite rational. Surely good documentation can address the
‘third generation’ issue.

On the other hand, it has been a long time since we have had the email list
meta virus “C++_in_kernel” break out. I’ve missed it.

To address some other point: there is obviously a lack of standard C++
runtime support in the kernel. Technically there is also a lack of standard
C runtime support as well, however as C doesn’t have global
constructors/destructors for non-intrinsic types it isn’t an obvious issue.
The work arounds for the lack of C++ runtime support are very well
documented here on ntdev and elsewhere.

=====================
Mark Roddy DDK MVP
Windows 2003/XP/2000 Consulting
Hollis Technology Solutions 603-321-1032
www.hollistech.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Jan Bottorff
Sent: Sunday, April 23, 2006 8:16 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

> Things like smart pointer classes which auto release
handles scare the
> crap out of me with respect to this goal.
> Yes, the pointer is freed automatically if the ref count
goes to zero,
> but who can figure that out w/out first having to delve
into a bunch
> of mix in classes to truly figure it out? Sometimes non automagic
> code is better, sometimes not.

That’s a curious argument. Isn’t the argument of why we
should use KMDF that Microsoft will just encapsulate a bunch
of stuff? And many things will just happen automagically?
Correct me if I’m wrong, but KMDF does not come with any
source code? So we will need to delve into a bunch of
disassembled code to truly figure out KMDF?

I didn’t invent smart pointers, any serious book on C++ talks
about them.
In many drivers, the data structures are complex enough that
you pretty much will have to use reference counting. The
question really is: is it easier to be SURE you keep all the
reference counts correct manually, or is it easier to let the
compiler do the work based on what you have described are the
semantics of a pointer.

Semantically, C treats the assignment of a pointer exactly
the same as the assignment of a simple integer. Storing 32
bits into a memory locations does not fully describe the semantics of:

aPtr = anotherPtr;

You may be destroying a reference to something, and that
something may now no longer be referenced by anything and
should be deallocated, and you may be adding a reference to
something else. To correctly describe these semantics in C,
at every assignment and when things go in or out of scope, a
programmer has to write code. You have to manually fill in
the semantics that can’t be described to the compiler.
Actually, I suppose you could encapsulate part of the
semantics in C, you make a function like
AClass_AssignPointer(AClass ** destination, AClass * source),
and the function manages the reference counts in AClass. So
now the C vs. C++ examples look like:

void aCFunc(void)
{
AClass * ptr;


AClass_AssignPointer(&ptr, newPointer);
if (ptr->flag)…

}

And the C++ with smart pointer example would be:

void aCPPFunc(void)
{
ReferenceCountedPtr ptr;
>
> …
> ptr = newPtr;
> if (ptr->flag)…
> …
> }
>
> Except the C++ example correctly decrements the reference to
> newPtr when ptr goes out of scope, and the C example doesn’t,
> so the programmer will still have to manually remember to
> decrement the reference count before exiting aCFunc. The C++
> example knows to decrement the reference count even if you
> put a return in the middle of the function. There is another
> bug in the C example, ptr is uninitialized, so
> AClass_AssignPointer will probably fault when it tries to
> decrement the reference count of a garbage pointer, or worse,
> it doesn’t fault and decrements a random location in memory
> (and that other driver crashes the system because its pointer
> just changed). Did I mention the smart pointer knows to set
> itself to null when it comes into scope, so the whole class
> of uninitialized pointer errors can’t happen anymore. The
> correct version would be:
>
> void aCFunc(void)
> {
> AClass * ptr = NULL;
>
> …
> AClass_AssignPointer(&ptr, newPointer);
> if (ptr->flag)…
> …
> if (ptr)
> if (InterlockedDecrement(&ptr->rc) == 0)
> destroy the object
> }
>
> Let’s look at the opportunities for bugs and their difficulty
> to find. If the programmer forgets the “= NULL”, we may
> corrupt random memory(undetectable automatically/possible
> system crash later, nasty) or we may just fault now (easy to
> detect, crash should point to location). If the programmer
> inserts a “return” in the middle or forget’s the test/destroy
> at the end we may have a memory leak(easy to detect the leak,
> variable on how hard to find the cause). If the programmer
> assigns ptr directly without also managing the reference
> counts, we may have a memory leak(easy to detect the leak,
> variable on how hard to find the cause). A smart pointer
> could not have any of these errors.
>
> It only takes one really simple mix in class to do reference
> counting, and one not very large template class to define
> smart pointers. To design these classes does require that you
> understand some advanced C++ like assignment and pointer
> dereferencing are overridable operators. It was certainly a
> strange concept when I first was exposed to it. To use these
> classes doesn’t take as much understanding, although it can
> be helpful for debugging.
>
> To be squeaky clear, using smart pointers in drivers on
> occasion requires you to manually maintain the reference
> count. Specifically, if you store a pointer to an object
> someplace that isn’t a smart pointer, like a context PVOID
> used in a callback (which you cast back into an object
> pointer in the callback). You then need to decrement the
> reference count when that PVOID reference goes away. Another
> little gotcha is if your store objects in a list using the
> standard OS list functions. Even though you are referencing
> into the middle of the object, the OS list functions will not
> automatically maintain the reference counts. My solution was
> to make a ReferenceCountedList template class for lists that
> also keeps the reference counts correct.
>
> I know that language choices are deeply rooted beliefs. All I
> can do is tell you about my language beliefs and my reasoning
> behind those beliefs, and listen to your language beliefs and
> learn about your choices. My language beliefs have certainly
> evolved over the years, and assume your beliefs also evolve.
> I personally think in general C++ is not a very good
> language, although I have learned to use it in ways that I
> believe make it better than C for writing drivers.
>
> - Jan
>
>
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online
> at http://www.osronline.com/page.cfm?name=ListServer
>

There is some progress, but nothing that will make it in time for Vista.
Not only must the compiler folks bring the support into the tool chain,
we need to verify that it works as advertised and that takes some time
;).

d

– I can spell, I just can’t type.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark Roddy
Sent: Sunday, April 23, 2006 7:24 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

Any progress convincing the compiler folks to fix this problem?

=====================
Mark Roddy DDK MVP
Windows 2003/XP/2000 Consulting
Hollis Technology Solutions 603-321-1032
www.hollistech.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Saturday, April 22, 2006 1:14 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

You can get 1) and 2) just by using a .cpp file and then using C BTW.
/W4 also gets you most of the way in C.

> However I came accross a memory optimization problem, when I add an
object my template does something like :

Please tell me you are not using templates. If you are don’t
try to make any function pageable, otherwise the linker may
place templacized code in the wrong segment.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Edouard A.
Sent: Saturday, April 22, 2006 8:24 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

The reason why I use C++ instead of plain C are :

  • Strict type checking;
  • In place declaration of variables;
  • Object-oriented programming (although you have to be
    cautious with what you use).

However C++ will not make your driver better or worse than if
written in C, because the only real influence on software
quality is the person behind the keyboard.

Anyways, after reading what Loren said I think I should write
a driver in pure assembly and hand over maintenance to a newbie. :stuck_out_tongue:

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of MM
Sent: Saturday, April 22, 2006 15:04
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Placement new operator in a driver

Curious, but what is the purpose of C++ in a driver? Other
than added problems such as this, why?

Sorry, couldn’t resist sparking this one again… But
really, all of this can be done in C, so what’s the point in
using C++ where there will be added problems/hassles?

Driver Works is proof drivers shouldn’t be written in C++ (of
all their developers and dollars, they never got it right).

Well, my gas can is now empty - I’m sure I’ll have some
interesting reading later… :slight_smile:

m.

Jan Bottorff wrote:

>Can you tell us EXACTLY what error you get?
>
>- Jan
>
>
>
>
>>Yes I did, that’s what I don’t undestand.
>>
>>The operator profile is something like this :
>>
>>class CMyBaseClassWithOperatorSomething { //…
>> // with placement
>> void *operator new(size_t lSize, void *pBuffer);
>> // without placement
>> void *operator new(size_t lSize);
>>//…
>>};
>>
>>Perhaps a typo somewhere, I shouldn’t minimize the impact of my own
>>stupidity. :wink:
>>
>>
>
>
>
>—
>Questions? First check the Kernel Driver FAQ at
>http://www.osronline.com/article.cfm?id=256
>
>To unsubscribe, visit the List Server section of OSR Online at
>http://www.osronline.com/page.cfm?name=ListServer
>
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer




Wanadoo vous informe que cet e-mail a ete controle par
l’anti-virus mail.
Aucun virus connu a ce jour par nos services n’a ete detecte.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Yeah so get the source code for toolX or don’t use it. That applies to toolX
no matter what language it is written in. It is in fact one of your big
gripes about KMDF, a gripe I heartily agree with.

I would never recommend that a customer of mine use a third party toolkit
that they did not have source access to. That is just asking for trouble,
and the trouble that will arise will get blamed at least partially on the
person who brought the toolkit into the development process to begin with.

On the other hand I have customers who are using C++ based kernel drivers
that have been commercially deployed for years, have undergone numerous
evolutionary changes all of which were greatly facilitated by the original
object oriented design, and have never experienced any of the fabled dark
pitfalls of C++ in the kernel.

=====================
Mark Roddy DDK MVP
Windows 2003/XP/2000 Consulting
Hollis Technology Solutions 603-321-1032
www.hollistech.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Don Burn
Sent: Sunday, April 23, 2006 9:02 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Placement new operator in a driver

“Edouard A.” wrote in message
> news:xxxxx@ntdev…
> > What matters is what tool is right for you. If you prefer
> C, by all
> > means use it.
>
> Sorry it is not what is the right tool for you, it is the
> right tool for your customer. Almost all of us work for
> someone directly or indirectly, the responsible professional
> will address the customers needs. If the firm has a lot of
> toolX experience and is likely to keep a continuing staff
> with experience in the kernel in toolX then consider using
> toolX. But if toolX is outside of the Microsoft driver
> development norm, think of all the
> challenges:
>
> 1. If you are one of the first employees for Windows
> kernel development, is toolX something that is going to be
> easy to hire people with experience in using it for Windows drivers?
>
> 2. If this is a contract, or a short time put together a
> team for a specific goal, how is a customer going to deal in
> the future when they need a bug fix for something based on
> toolX? This could mean a lot of studying, or even a rewrite
> if there is a problem and you are gone.
>
> 3. The hardest to qualify: is toolX likely to give a
> benefit of a high enough multiplier to justify the risk? I
> typically look for a 2 times multiplier as the lowest to
> consider for a using a product outside the norm.
> This multiplier needs to be thought of for the first 2 years
> or more of the product shipments, not just development.
>
>
> Now you can replace the term toolX with C++, a third party
> toolkit, or something else. I don’t count Microsoft efforts
> such as KMDF, UMDF, mini-filters, WMI libraries, etc in this.
> The Microsoft efforts are going to go mainstream, and the
> people resources will be there in the future.
>
> A good professional will consider the questions above (and
> others I’m sure people can offer) before using toolX whatever
> it will be. We should be doing our best for our customers
> and the end users, a particular technology is a secondary (or
> lower) consideration.
>
> As a consultant I have had to tell customers the best thing
> they could do is throw out the tool and the code (and in one
> instance the development team).
> This is not something anyone wants, but using a toolX can
> cause this to happen. This is why one should look carefully
> before going outside the Microsoft guidelines, the company
> and job you save by avoiding “something special” could be your own.
>
>
>
> –
> Don Burn (MVP, Windows DDK)
> Windows 2k/XP/2k3 Filesystem and Driver Consulting Remove
> StopSpam from the email to reply
>
>
>
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online
> at http://www.osronline.com/page.cfm?name=ListServer
>


That’s a curious argument. Isn’t the argument of why we should use KMDF
that
Microsoft will just encapsulate a bunch of stuff? And many things will
just
happen automagically? Correct me if I’m wrong, but KMDF does not come
with
any source code? So we will need to delve into a bunch of disassembled
code
to truly figure out KMDF?

No, KMDF is not just an encapsulation of some stuff. KMDF is an
integration of all the different rules and concepts into one unified
presentation. But that is not the point. KMDF’s goal is to prevent the
need for this type of stuff to begin with (at least with respect to
tracking references and managing pointer lifetime). 9 times out of 10,
a driver writer doesn’t have to deal with object destruction or even ref
counting at all, it just works. The difference here is that it works at
a higher level of abstraction and there is no need to have automagic
smart classes which handle this type of stuff, you can just write the
code to use the object and be done with it.

So, yes, this is takes a little getting used to…but this is common
across all KMDF drivers, not just one driver written by one person. It
is pervasive across all of them. There is no hidden meaning behind
overloaded operators (more power to you, I avoid them like the plague
b/c you can’t tell what is what anymore (*) ), just straight forward
code.

D

(*) I was just debugging another component as a favor to another team
and it took me *two* days of looking over the code to see that there was
an overloaded operator=() that was doing all the magic. Not the best
use of my time nor the best use of the language.

– I can spell, I just can’t type.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Jan Bottorff
Sent: Sunday, April 23, 2006 5:16 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

Things like smart pointer classes which
auto release handles scare the crap out of me with respect to this
goal.
Yes, the pointer is freed automatically if the ref count goes to zero,
but who can figure that out w/out first having to delve into a bunch
of
mix in classes to truly figure it out? Sometimes non automagic code
is
better, sometimes not.

That’s a curious argument. Isn’t the argument of why we should use KMDF
that
Microsoft will just encapsulate a bunch of stuff? And many things will
just
happen automagically? Correct me if I’m wrong, but KMDF does not come
with
any source code? So we will need to delve into a bunch of disassembled
code
to truly figure out KMDF?

I didn’t invent smart pointers, any serious book on C++ talks about
them.
In many drivers, the data structures are complex enough that you pretty
much
will have to use reference counting. The question really is: is it
easier to
be SURE you keep all the reference counts correct manually, or is it
easier
to let the compiler do the work based on what you have described are the
semantics of a pointer.

Semantically, C treats the assignment of a pointer exactly the same as
the
assignment of a simple integer. Storing 32 bits into a memory locations
does
not fully describe the semantics of:

aPtr = anotherPtr;

You may be destroying a reference to something, and that something may
now
no longer be referenced by anything and should be deallocated, and you
may
be adding a reference to something else. To correctly describe these
semantics in C, at every assignment and when things go in or out of
scope, a
programmer has to write code. You have to manually fill in the semantics
that can’t be described to the compiler. Actually, I suppose you could
encapsulate part of the semantics in C, you make a function like
AClass_AssignPointer(AClass ** destination, AClass * source), and the
function manages the reference counts in AClass. So now the C vs. C++
examples look like:

void aCFunc(void)
{
AClass * ptr;


AClass_AssignPointer(&ptr, newPointer);
if (ptr->flag)…

}

And the C++ with smart pointer example would be:

void aCPPFunc(void)
{
ReferenceCountedPtr ptr;


ptr = newPtr;
if (ptr->flag)…

}

Except the C++ example correctly decrements the reference to newPtr when
ptr
goes out of scope, and the C example doesn’t, so the programmer will
still
have to manually remember to decrement the reference count before
exiting
aCFunc. The C++ example knows to decrement the reference count even if
you
put a return in the middle of the function. There is another bug in the
C
example, ptr is uninitialized, so AClass_AssignPointer will probably
fault
when it tries to decrement the reference count of a garbage pointer, or
worse, it doesn’t fault and decrements a random location in memory (and
that
other driver crashes the system because its pointer just changed). Did I
mention the smart pointer knows to set itself to null when it comes into
scope, so the whole class of uninitialized pointer errors can’t happen
anymore. The correct version would be:

void aCFunc(void)
{
AClass * ptr = NULL;


AClass_AssignPointer(&ptr, newPointer);
if (ptr->flag)…

if (ptr)
if (InterlockedDecrement(&ptr->rc) == 0)
destroy the object
}

Let’s look at the opportunities for bugs and their difficulty to find.
If
the programmer forgets the “= NULL”, we may corrupt random
memory(undetectable automatically/possible system crash later, nasty) or
we
may just fault now (easy to detect, crash should point to location). If
the
programmer inserts a “return” in the middle or forget’s the test/destroy
at
the end we may have a memory leak(easy to detect the leak, variable on
how
hard to find the cause). If the programmer assigns ptr directly without
also
managing the reference counts, we may have a memory leak(easy to detect
the
leak, variable on how hard to find the cause). A smart pointer could not
have any of these errors.

It only takes one really simple mix in class to do reference counting,
and
one not very large template class to define smart pointers. To design
these
classes does require that you understand some advanced C++ like
assignment
and pointer dereferencing are overridable operators. It was certainly a
strange concept when I first was exposed to it. To use these classes
doesn’t
take as much understanding, although it can be helpful for debugging.

To be squeaky clear, using smart pointers in drivers on occasion
requires
you to manually maintain the reference count. Specifically, if you store
a
pointer to an object someplace that isn’t a smart pointer, like a
context
PVOID used in a callback (which you cast back into an object pointer in
the
callback). You then need to decrement the reference count when that
PVOID
reference goes away. Another little gotcha is if your store objects in a
list using the standard OS list functions. Even though you are
referencing
into the middle of the object, the OS list functions will not
automatically
maintain the reference counts. My solution was to make a
ReferenceCountedList template class for lists that also keeps the
reference
counts correct.

I know that language choices are deeply rooted beliefs. All I can do is
tell
you about my language beliefs and my reasoning behind those beliefs, and
listen to your language beliefs and learn about your choices. My
language
beliefs have certainly evolved over the years, and assume your beliefs
also
evolve. I personally think in general C++ is not a very good language,
although I have learned to use it in ways that I believe make it better
than
C for writing drivers.

- Jan


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Well note it is more than just having the source, it is understanding it,
knowing its flaws and being able to support it. That has always been the
flaw of the Open Source movement, they assume the source is all you need.
Even with the source you can be in serious trouble.

For instance consider a customer I had last year, they had a driver written
with a popular toolkit and it was not working. I advised them I was not
experienced with the toolkit, but they had already asked several other
consultants for help and none of them were experienced. I took the job of
doing some simple checks on the code, mainly using various static and
dynamic code checkers and then reviewing the areas around the problems. I
expected the results to be bunch of problems in the customers code and a
solid toolkit. Instead I got zero hits on the customers code, but almost
500 serious flaws (unitialized pointers, malformed C++, etc) in the toolkit.
After the review, I told them to sue the firm and junk the toolkit.

I know a number of firms that use C++ in the kernel, this is fine it works
for them. I don’t use C++ in the kernel, since I have not seen the benefits
I spoke of in my first post, but having been on the C++ standards committee
and having worked in C++ compilers I certainly see the problems that can
arise.

Each company needs to make the choice themselves, but there are now tools
available the eliminate the type safety and other checking arguments without
wandering in to C++. If you feel the encapuslation and OO capabilities are
worth it, versus the lack of support and the potential problems, then use
C++.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Remove StopSpam from the email to reply

“Mark Roddy” wrote in message news:xxxxx@ntdev…
> Yeah so get the source code for toolX or don’t use it. That applies to
> toolX
> no matter what language it is written in. It is in fact one of your big
> gripes about KMDF, a gripe I heartily agree with.
>
> I would never recommend that a customer of mine use a third party toolkit
> that they did not have source access to. That is just asking for trouble,
> and the trouble that will arise will get blamed at least partially on the
> person who brought the toolkit into the development process to begin with.
>
> On the other hand I have customers who are using C++ based kernel drivers
> that have been commercially deployed for years, have undergone numerous
> evolutionary changes all of which were greatly facilitated by the original
> object oriented design, and have never experienced any of the fabled dark
> pitfalls of C++ in the kernel.
>
>

The purpose of C++ in a driver is the same as the purpose of using it
anywhere else: he wants to for reasons that make sense to him. Clearly,
one does not need C++ to write drivers. I hear you on taking issue with
the nonsense about why some projects simply must have it. In my
opinion, a cursory examination of the history of abject software
development failures will reveal several common traits, one of which is
the insistence on using a new programming language because nothing can
not be done without it. I’m not sure how anyone every really bought in
to this, not for technical reasons, but the much more base on: the
recommendation usually comes from outside consulatants, who, curiously,
chose something that no one in the company knows. Go figure. C++ is no
exception to this trend; consult Mentor Graphics, the IRS, Borland or
basically anyone who adopted early on, who was not Bell Labs. It took
the rest of us more than a little time to catch up. That being said, I
can’t help but wonder, were this a list for Windows development, might
the argument be that C++ is an absolute necessity. That I seriously
doubt that any one seriously entertains ideas that Windows development
would be easier/better/safer without MFC, notwithstanding.

While I categorically agree with your assertion that DriverWorks sucks
in the largest way possible, I think you have stated a reason which is
simply not true. DriverWorks for the same reason that absolutely
everything else that has ever come with SoftICE has: they never put any
time, effort or money in to the products. DriverWorks was at least
arguably useful; that is, compare it to, say, whatever cliche of a name
that Compuware used to identify any and all of the fine, fine Visual
Basic utilities that were
“value added” to SoftICE and/or BoundChecker. Were it not for the fact
that these products (along with a subscription service, that, to be
fair, in the case of SoftICE only, was not only fair, but, really,
necessary) were used as the basis for doubling to tripling the price, I
would call them handouts. Handouts is really my point. They acquired
them (as I recall, and this very well may only be part of the truth, or
just flat out incorrect), the Visual Basic products were the developed
by the same person/company who came up the whole Universal Display
Driver based on DirectDraw. This idea was fabulous, and, in my opinion,
absolutely vital to the continued success of the product. As a daily
user of SoftICE/Visual SoftICE (although I also use WinDbg daily; much
more in fact), it is unfortunate that it is no more. That being said,
while I don’t begrudge anyone for attempting to market a product as well
as they can, in this case, I would, hypocritically, say that Compuware
got what they deserved, because what they did was kind of abusive - they
followed the Microsoft model of packaging shitty products with ones of
exceptional value (for example, originally, any of the garbage that came
with Word and Excel). I have no issues with Microsoft’s tact on this,
because they differ in to important ways. The first is that, while
something like Access is a poor excuse for a database product, at least
in the market in which it was advertised, the basically gave it away.
The second, and, much, much more important, in my opinion, is that they
didn’t just keep pandering their acquired garbage; they improved it, and
changed the advertising to target a market for which it is more than
adequate, and still, essentially, free, assuming that one is buying
Office for something else in addition to Access.

MM

>> xxxxx@comcast.net 2006-04-22 09:03 >>>
Curious, but what is the purpose of C++ in a driver? Other than added
problems such as this, why?

Sorry, couldn’t resist sparking this one again… But really, all of
this can be done in C, so what’s the
point in using C++ where there will be added problems/hassles?

Driver Works is proof drivers shouldn’t be written in C++ (of all their

developers and dollars, they never got it right).

Well, my gas can is now empty - I’m sure I’ll have some interesting
reading later… :slight_smile:

m.

Jan Bottorff wrote:

Can you tell us EXACTLY what error you get?

  • Jan

>Yes I did, that’s what I don’t undestand.
>
>The operator profile is something like this :
>
>class CMyBaseClassWithOperatorSomething
>{
>//…
> // with placement
> void *operator new(size_t lSize, void *pBuffer);
> // without placement
> void *operator new(size_t lSize);
>//…
>};
>
>Perhaps a typo somewhere, I shouldn’t minimize the impact of my own
>stupidity. :wink:
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

LOREN:

I think your being extravagant. This could all be done with a
plugboard.

>> xxxxx@earthlink.net 2006-04-22 10:13 >>>
Sorry, couldn’t resist sparking this one again… But really, all
of
this can be done in C, so what’s the
point in using C++ where there will be added problems/hassles?

All of this can be done in assembler, at least on 8086 machines. Why
bother
with the hassles of learning C?

For that matter, with a little creativity you ought to be able to write
a
network driver in hex using Notepad and an ascii to hex converter.
Why
bother finding an assembler somewhere to download and the hassle of
learning
all those mnemonics?

Loren


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

This is definitely true. I learned about this one and the related
problem of virtual destructors in the hardest of possible ways. That
being said, while there are very real constraints on what you can safely
do, and you really, really must either understand them or being willing
to suffer until you do, I still use aspects of C++ in the kernel, mostly
because I like to.

>> xxxxx@microsoft.com 2006-04-22 13:13 >>>
You can get 1) and 2) just by using a .cpp file and then using C BTW.
/W4 also gets you most of the way in C.

However I came accross a memory optimization problem, when I add an
object my template does something like :

Please tell me you are not using templates. If you are don’t try to
make any function pageable, otherwise the linker may place templacized
code in the wrong segment.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Edouard A.
Sent: Saturday, April 22, 2006 8:24 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

The reason why I use C++ instead of plain C are :

  • Strict type checking;
  • In place declaration of variables;
  • Object-oriented programming (although you have to be cautious with
    what
    you use).

However C++ will not make your driver better or worse than if written
in
C,
because the only real influence on software quality is the person
behind
the
keyboard.

Anyways, after reading what Loren said I think I should write a driver
in
pure assembly and hand over maintenance to a newbie. :stuck_out_tongue:

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of MM
Sent: Saturday, April 22, 2006 15:04
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Placement new operator in a driver

Curious, but what is the purpose of C++ in a driver? Other than added
problems such as this, why?

Sorry, couldn’t resist sparking this one again… But really, all of
this
can be done in C, so what’s the point in using C++ where there will be
added
problems/hassles?

Driver Works is proof drivers shouldn’t be written in C++ (of all
their
developers and dollars, they never got it right).

Well, my gas can is now empty - I’m sure I’ll have some interesting
reading
later… :slight_smile:

m.

Jan Bottorff wrote:

Can you tell us EXACTLY what error you get?

  • Jan

>Yes I did, that’s what I don’t undestand.
>
>The operator profile is something like this :
>
>class CMyBaseClassWithOperatorSomething { //…
> // with placement
> void *operator new(size_t lSize, void *pBuffer);
> // without placement
> void *operator new(size_t lSize);
>//…
>};
>
>Perhaps a typo somewhere, I shouldn’t minimize the impact of my own
>stupidity. :wink:
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer



Wanadoo vous informe que cet e-mail a ete controle par l’anti-virus
mail.
Aucun virus connu a ce jour par nos services n’a ete detecte.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

100% correct, Don.

>> xxxxx@acm.org 2006-04-23 09:02 >>>

“Edouard A.” wrote in message
news:xxxxx@ntdev…
> What matters is what tool is right for you. If you prefer C, by all

> means
> use it.

Sorry it is not what is the right tool for you, it is the right tool
for
your customer. Almost all of us work for someone directly or
indirectly,
the responsible professional will address the customers needs. If the
firm
has a lot of toolX experience and is likely to keep a continuing staff
with
experience in the kernel in toolX then consider using toolX. But if
toolX
is outside of the Microsoft driver development norm, think of all the
challenges:

1. If you are one of the first employees for Windows kernel
development, is toolX something that is going to be easy to hire people
with
experience in using it for Windows drivers?

2. If this is a contract, or a short time put together a team for
a
specific goal, how is a customer going to deal in the future when they
need
a bug fix for something based on toolX? This could mean a lot of
studying,
or even a rewrite if there is a problem and you are gone.

3. The hardest to qualify: is toolX likely to give a benefit of a
high
enough multiplier to justify the risk? I typically look for a 2 times

multiplier as the lowest to consider for a using a product outside the
norm.
This multiplier needs to be thought of for the first 2 years or more of
the
product shipments, not just development.

Now you can replace the term toolX with C++, a third party toolkit, or

something else. I don’t count Microsoft efforts such as KMDF, UMDF,
mini-filters, WMI libraries, etc in this. The Microsoft efforts are
going
to go mainstream, and the people resources will be there in the
future.

A good professional will consider the questions above (and others I’m
sure
people can offer) before using toolX whatever it will be. We should be

doing our best for our customers and the end users, a particular
technology
is a secondary (or lower) consideration.

As a consultant I have had to tell customers the best thing they could
do is
throw out the tool and the code (and in one instance the development
team).
This is not something anyone wants, but using a toolX can cause this to

happen. This is why one should look carefully before going outside the

Microsoft guidelines, the company and job you save by avoiding
“something
special” could be your own.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Remove StopSpam from the email to reply


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Can you be more specific, please? Can you provide any example of a templated
function placed in a paged segment? What was the problem with virtual
destructors?

Thanks

“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
> This is definitely true. I learned about this one and the related
> problem of virtual destructors in the hardest of possible ways. That
> being said, while there are very real constraints on what you can safely
> do, and you really, really must either understand them or being willing
> to suffer until you do, I still use aspects of C++ in the kernel, mostly
> because I like to.
>
>
>
>>>> xxxxx@microsoft.com 2006-04-22 13:13 >>>
> You can get 1) and 2) just by using a .cpp file and then using C BTW.
> /W4 also gets you most of the way in C.
>
>> However I came accross a memory optimization problem, when I add an
> object my template does something like :
>
> Please tell me you are not using templates. If you are don’t try to
> make any function pageable, otherwise the linker may place templacized
> code in the wrong segment.
>
> d
>

The problem with templates is that the #pragmas around them do not
apply. Where the code is instantiated is a non deterministic. I worked
on a failed project that used templates in a driver where the section in
which the generated code for a template moved from build to build
depending on minor changes elsewhere in the binary. It would blow up at
random spots where code was not supposed to be pageable, but it was.
Basically, the only workaround is to have a completely non pageable
driver.

As for virtual destructors, the gotcha here is that the linker remove
identical functions. Many classes virtual destructor is the exactly the
same code so you see only one or two of them that are shared in the
entire class hierarchy. The pageability of this function is not a
criteria for uniqueness so you can get a virtual desctructor that should
be NP put in a pageable section. Templates make this worse b/c of the
even more randomness of the section that they generate code in.

Note that this does not apply only the desctructors but any function.
Another likely candidate are accessor functions like this

ULONG GetCount(VOID) { return m_Count; }

Where m_Count’s offset is 0x4. Any other accessor function which
returns a ULONG where the field resides at offset 0x4 will share the
function implementation even though they are not in the same class.
This also has the nasty side affect of making callstacks look very
strange and can lead to some initial false positives, such as

Bar::~Bar()
Foo::DestroySelf()
Foo::RunDown()

Where ~Bar() is a virtual destructor and where ~Foo() matches it, so the
compiler just uses ~Bar() instead of ~Foo().

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of cristalink
Sent: Sunday, April 23, 2006 1:45 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Placement new operator in a driver

Can you be more specific, please? Can you provide any example of a
templated
function placed in a paged segment? What was the problem with virtual
destructors?

Thanks

“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
> This is definitely true. I learned about this one and the related
> problem of virtual destructors in the hardest of possible ways. That
> being said, while there are very real constraints on what you can
safely
> do, and you really, really must either understand them or being
willing
> to suffer until you do, I still use aspects of C++ in the kernel,
mostly
> because I like to.
>
>
>
>>>> xxxxx@microsoft.com 2006-04-22 13:13 >>>
> You can get 1) and 2) just by using a .cpp file and then using C BTW.
> /W4 also gets you most of the way in C.
>
>> However I came accross a memory optimization problem, when I add an
> object my template does something like :
>
> Please tell me you are not using templates. If you are don’t try to
> make any function pageable, otherwise the linker may place templacized
> code in the wrong segment.
>
> d
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I haven’t looked at this problem in quite a while, as my experiences
with them convinced me to avoid them where I was not willing to check
out the generated code extensively. I can give you an example for
virtual destructors; not for templates (I explain why later). The basic
problem with virtual destructors is the same as that with templates:
code can end up in pageable segments, which can (and generally will)
cause problems that I’m sure your familiar with. The significant
difference is that the manifestations of the case of virtual destructors
can be, to a significant extent, predicted and worked around. That
being said, I rarely do so, as it is cumbersome, ugly, quite possibly
likely to break when the compiler changes, and, in the case of the
kernel, avoidable by changing the representation. Normally, this is, in
my opinion, about the worst thing one can do; however, in this case, the
reasons are cogent. Unfortunately, as my principal motivation for using
C++ in the kernel (anywhere I roam, really) is templates, this is of no
help here.

Please keep in mind that this is all empirical, and likely to change
with the compiler.

For every version of VC++ that I have looked at closely (which does not
include the most recent one, and, possibly the penultimate one as well),
the section in to which the code for a destructor is emitted depends on
whether it is virtual or not. In the case of a non virtual destructor,
the code (appears, at least) to go in to the same section as the first
code that references it; for the virtual case, it (again, appears) to go
in to the section that contains a reference to a constructor. The
specific situation in which this causes a problem is when the first
constructor (for a class with a virtual destructor) appears in the INIT
(or other discardable) section, and reference to the virtual destructor
occurs after it is discarded. The particularly nasty (and not
automatably addresable) complication of this is that this will occur if
any of the classes base classes (if any) satisfy the same conditions and
appear in the INIT section. There is no reasonable way to ensure that
this does not occur, other than to avoid the use of virtual destructors
completely, or using the following, rather brutal hack, that, as I
mentioned, I do not use (with a few specific exceptions that I have
researched extensively; that being said, it is probably still not the
best idea, but rather one that I have gotten away with, and very
possibly will be able to continue to do so, at least in the very
meaningful sense (in my particular case, which is unusual, but,
unfortunately, I may not describe)). Additional fun can be had because
the compiler will generate destructors for scalar and vector deletion,
and these, if unspecified and not worked around, will end up in INIT
under the same conditions. OK, one more twist. The later only occurs
for checked builds.

A work around to this, such as it is, is that to do the best you can to
ensure this issue, for any class that uses a virtual destructor, and the
at least one constructor for this class will occur in a pageable section
(under the conditions described above), you must create another
constructor (that may just be empty) that appears in the same source
module as the one that will appear in the INIT section, and it must
occur before that constructor. As mentioned above, but reiterated here
because it is very easy to overlook, this is true for any class that
derives from a class which contains a virtual destructor. If all of
this sounds very suspect, I would tell you that it seems to work, and
then agree with you. The only confirmation, such as it is, that I can
offer you, is that I came up with this independently of DriverWorks (but
not, by a long shot, on my own), and we seem to agree. Normally, this
would be comforting; however, as has been pointed out many times in this
list (and I don’t think I have ever seen anyone disagree), DriverWorks
is a proverbial Piece of Shit, so I don’t know what this really offers.

I’m sorry, but I can not offer you a concrete example that I know
exhibits it, because of the nature of the work in which I am involved.
This, however, is, to the best of my understanding and research,
entirely accurate, including the part about it being labile.

The situation for templates is much, much worse, in the sense of being,
without access to the source code for the compiler in question, there is
really no way (that I know of) to detail this conditions that dictate
where any piece of instantiated templated code might appear. Formally,
the whole issue is a Halting problem, and, as many such issues due,
almost assuredly does have an answer, but not one that can be relied
upon, unless, of course, you happen to know it. Ironically, and some
would, quite reasonably, say foolishly, I basically don’t use virtual
destructors, and I do, quite causiously, use templates.

The long and short of this is that, to be safe as possible, you have to
look at complete map file, searching for the particulars, taking in to
account the base class issue. This is very difficult, as well as time
consuming, so I have to really, really want something to do it. I have
written a tool (or modified an existing tool) that does, reliably, it
seems, process images using the symbols to verify that particular
instances of this problem are not occuring. This, of course, only works
by my specifying accurately and without fail, what it should look for.

I don’t imagine this helped very much, but this is, unfortunately, the
best I have to offer. The best source of information I can point you to
on this, is the documentation for DriverWorks, if you have access to it.
I, presumably, may not include or note it, due to licensing issues.
And, finally, as noted above, the product, well, sucks. The long and
short is that, using these features of C++ (not to mention exception
handling), needs to be carefully weighed against the potential downside.
In my case, which is, I think, unusual, I find it to be worth it.

MM

>> xxxxx@cristalink.com 2006-04-23 16:44 >>>
Can you be more specific, please? Can you provide any example of a
templated
function placed in a paged segment? What was the problem with virtual
destructors?

Thanks

“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
> This is definitely true. I learned about this one and the related
> problem of virtual destructors in the hardest of possible ways.
That
> being said, while there are very real constraints on what you can
safely
> do, and you really, really must either understand them or being
willing
> to suffer until you do, I still use aspects of C++ in the kernel,
mostly
> because I like to.
>
>
>
>>>> xxxxx@microsoft.com 2006-04-22 13:13 >>>
> You can get 1) and 2) just by using a .cpp file and then using C
BTW.
> /W4 also gets you most of the way in C.
>
>> However I came accross a memory optimization problem, when I add an
> object my template does something like :
>
> Please tell me you are not using templates. If you are don’t try to
> make any function pageable, otherwise the linker may place
templacized
> code in the wrong segment.
>
> d
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

DORON:

I just wrote a long, fairly unclear, explanation to the dev on my
experience with this subject. You, as, in addition to describing the
same issues I mentioned (both at greater at length yet considerably less
clearly than you), have identified some very troubling ones that I have
never even considered, seem to know quite a bit more about this than I.
I was wondering, for my own benefit, if not the dev’s, if you wouldn’t
mind reading what I wrote and telling me what you think. Even though,
based on stability of the work I do (which is entirely research), I
don’t think I’ve run in to the accessor issue, I would greatly
appreciate this, as it sounds like, effectively, a deal breaker, the
tool I’ve written and the fact that I make use of the template features
(and no others that I am aware of) only when it just irritates too much
to go without. Not the best reason, but what can I tell you. In
particular, I’m confused about a few things.

  1. For the accessor issue, this is true only for functions within the
    heirarchy?
  2. How does inlining (aside from unpredictably) factor in to this?
  3. Purely as a hypothetical (as I can imagine ever doing this), could
    a pair of non member functions that act essentially as accessors to
    global variable(s) exhibit this behavior? If forced to come up an
    example, I suppose that accessors to some sort of global union could do
    this, if it applies.

This is not exactly pressing stuff, but, if you wouldn’t mind, I would
really appreciate you input.

Thanks,

M. M. O’Brien

>> xxxxx@microsoft.com 2006-04-23 17:22 >>>
The problem with templates is that the #pragmas around them do not
apply. Where the code is instantiated is a non deterministic. I
worked
on a failed project that used templates in a driver where the section
in
which the generated code for a template moved from build to build
depending on minor changes elsewhere in the binary. It would blow up
at
random spots where code was not supposed to be pageable, but it was.
Basically, the only workaround is to have a completely non pageable
driver.

As for virtual destructors, the gotcha here is that the linker remove
identical functions. Many classes virtual destructor is the exactly
the
same code so you see only one or two of them that are shared in the
entire class hierarchy. The pageability of this function is not a
criteria for uniqueness so you can get a virtual desctructor that
should
be NP put in a pageable section. Templates make this worse b/c of the
even more randomness of the section that they generate code in.

Note that this does not apply only the desctructors but any function.
Another likely candidate are accessor functions like this

ULONG GetCount(VOID) { return m_Count; }

Where m_Count’s offset is 0x4. Any other accessor function which
returns a ULONG where the field resides at offset 0x4 will share the
function implementation even though they are not in the same class.
This also has the nasty side affect of making callstacks look very
strange and can lead to some initial false positives, such as

Bar::~Bar()
Foo::DestroySelf()
Foo::RunDown()

Where ~Bar() is a virtual destructor and where ~Foo() matches it, so
the
compiler just uses ~Bar() instead of ~Foo().

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of cristalink
Sent: Sunday, April 23, 2006 1:45 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Placement new operator in a driver

Can you be more specific, please? Can you provide any example of a
templated
function placed in a paged segment? What was the problem with virtual
destructors?

Thanks

“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
> This is definitely true. I learned about this one and the related
> problem of virtual destructors in the hardest of possible ways.
That
> being said, while there are very real constraints on what you can
safely
> do, and you really, really must either understand them or being
willing
> to suffer until you do, I still use aspects of C++ in the kernel,
mostly
> because I like to.
>
>
>
>>>> xxxxx@microsoft.com 2006-04-22 13:13 >>>
> You can get 1) and 2) just by using a .cpp file and then using C
BTW.
> /W4 also gets you most of the way in C.
>
>> However I came accross a memory optimization problem, when I add an
> object my template does something like :
>
> Please tell me you are not using templates. If you are don’t try to
> make any function pageable, otherwise the linker may place
templacized
> code in the wrong segment.
>
> d
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

>>The problem with templates is that the #pragmas around them do not apply

To my experience, templates are always placed in a non paged segment. I
would like to see sample code that proves otherwise. Besides, this may
depend on the compiler version. What was a problem in VC6 may no longer
apply in VC7.

>ULONG GetCount(VOID) { return m_Count; }

The solution is to use __forceinline, the “inline only those marked as
inline” switch, and to make sure the relevant warnings are enabled
(“function selected for inline expansion”, “function not inlined” etc).

>destructors

To my experience, constructors and destructors should (a) always be
explicitly defined, and (b) defined non-paged in .cpp. The compiler is free
to put an implicitly generated function to wherever it wants.

Cheers

“Doron Holan” wrote in message
news:xxxxx@ntdev…
The problem with templates is that the #pragmas around them do not
apply. Where the code is instantiated is a non deterministic. I worked
on a failed project that used templates in a driver where the section in
which the generated code for a template moved from build to build
depending on minor changes elsewhere in the binary. It would blow up at
random spots where code was not supposed to be pageable, but it was.
Basically, the only workaround is to have a completely non pageable
driver.

As for virtual destructors, the gotcha here is that the linker remove
identical functions. Many classes virtual destructor is the exactly the
same code so you see only one or two of them that are shared in the
entire class hierarchy. The pageability of this function is not a
criteria for uniqueness so you can get a virtual desctructor that should
be NP put in a pageable section. Templates make this worse b/c of the
even more randomness of the section that they generate code in.

Note that this does not apply only the desctructors but any function.
Another likely candidate are accessor functions like this

ULONG GetCount(VOID) { return m_Count; }

Where m_Count’s offset is 0x4. Any other accessor function which
returns a ULONG where the field resides at offset 0x4 will share the
function implementation even though they are not in the same class.
This also has the nasty side affect of making callstacks look very
strange and can lead to some initial false positives, such as

Bar::~Bar()
Foo::DestroySelf()
Foo::RunDown()

Where ~Bar() is a virtual destructor and where ~Foo() matches it, so the
compiler just uses ~Bar() instead of ~Foo().

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of cristalink
Sent: Sunday, April 23, 2006 1:45 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Placement new operator in a driver

Can you be more specific, please? Can you provide any example of a
templated
function placed in a paged segment? What was the problem with virtual
destructors?

Thanks



“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
> This is definitely true. I learned about this one and the related
> problem of virtual destructors in the hardest of possible ways. That
> being said, while there are very real constraints on what you can
safely
> do, and you really, really must either understand them or being
willing
> to suffer until you do, I still use aspects of C++ in the kernel,
mostly
> because I like to.
>
>
>
>>>> xxxxx@microsoft.com 2006-04-22 13:13 >>>
> You can get 1) and 2) just by using a .cpp file and then using C BTW.
> /W4 also gets you most of the way in C.
>
>> However I came accross a memory optimization problem, when I add an
> object my template does something like :
>
> Please tell me you are not using templates. If you are don’t try to
> make any function pageable, otherwise the linker may place templacized
> code in the wrong segment.
>
> d
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

According to my experience, all code, including templates, goes to a default
segment, which is non-paged. If one starts to mess with autogenerated code,
such as constructors, destructors, copy constructors etc, they are looking
for troubles. There is not much point in having constructors or destructors
paged, as they are usually short, at least my ones.

the documentation for DriverWorks, if you have access to it

No, thank you :slight_smile:

“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
>I haven’t looked at this problem in quite a while, as my experiences
> with them convinced me to avoid them where I was not willing to check
> out the generated code extensively. I can give you an example for
> virtual destructors; not for templates (I explain why later). The basic
> problem with virtual destructors is the same as that with templates:
> code can end up in pageable segments, which can (and generally will)
> cause problems that I’m sure your familiar with. The significant
> difference is that the manifestations of the case of virtual destructors
> can be, to a significant extent, predicted and worked around. That
> being said, I rarely do so, as it is cumbersome, ugly, quite possibly
> likely to break when the compiler changes, and, in the case of the
> kernel, avoidable by changing the representation. Normally, this is, in
> my opinion, about the worst thing one can do; however, in this case, the
> reasons are cogent. Unfortunately, as my principal motivation for using
> C++ in the kernel (anywhere I roam, really) is templates, this is of no
> help here.
>
> Please keep in mind that this is all empirical, and likely to change
> with the compiler.
>
> For every version of VC++ that I have looked at closely (which does not
> include the most recent one, and, possibly the penultimate one as well),
> the section in to which the code for a destructor is emitted depends on
> whether it is virtual or not. In the case of a non virtual destructor,
> the code (appears, at least) to go in to the same section as the first
> code that references it; for the virtual case, it (again, appears) to go
> in to the section that contains a reference to a constructor. The
> specific situation in which this causes a problem is when the first
> constructor (for a class with a virtual destructor) appears in the INIT
> (or other discardable) section, and reference to the virtual destructor
> occurs after it is discarded. The particularly nasty (and not
> automatably addresable) complication of this is that this will occur if
> any of the classes base classes (if any) satisfy the same conditions and
> appear in the INIT section. There is no reasonable way to ensure that
> this does not occur, other than to avoid the use of virtual destructors
> completely, or using the following, rather brutal hack, that, as I
> mentioned, I do not use (with a few specific exceptions that I have
> researched extensively; that being said, it is probably still not the
> best idea, but rather one that I have gotten away with, and very
> possibly will be able to continue to do so, at least in the very
> meaningful sense (in my particular case, which is unusual, but,
> unfortunately, I may not describe)). Additional fun can be had because
> the compiler will generate destructors for scalar and vector deletion,
> and these, if unspecified and not worked around, will end up in INIT
> under the same conditions. OK, one more twist. The later only occurs
> for checked builds.
>
> A work around to this, such as it is, is that to do the best you can to
> ensure this issue, for any class that uses a virtual destructor, and the
> at least one constructor for this class will occur in a pageable section
> (under the conditions described above), you must create another
> constructor (that may just be empty) that appears in the same source
> module as the one that will appear in the INIT section, and it must
> occur before that constructor. As mentioned above, but reiterated here
> because it is very easy to overlook, this is true for any class that
> derives from a class which contains a virtual destructor. If all of
> this sounds very suspect, I would tell you that it seems to work, and
> then agree with you. The only confirmation, such as it is, that I can
> offer you, is that I came up with this independently of DriverWorks (but
> not, by a long shot, on my own), and we seem to agree. Normally, this
> would be comforting; however, as has been pointed out many times in this
> list (and I don’t think I have ever seen anyone disagree), DriverWorks
> is a proverbial Piece of Shit, so I don’t know what this really offers.
>
> I’m sorry, but I can not offer you a concrete example that I know
> exhibits it, because of the nature of the work in which I am involved.
> This, however, is, to the best of my understanding and research,
> entirely accurate, including the part about it being labile.
>
> The situation for templates is much, much worse, in the sense of being,
> without access to the source code for the compiler in question, there is
> really no way (that I know of) to detail this conditions that dictate
> where any piece of instantiated templated code might appear. Formally,
> the whole issue is a Halting problem, and, as many such issues due,
> almost assuredly does have an answer, but not one that can be relied
> upon, unless, of course, you happen to know it. Ironically, and some
> would, quite reasonably, say foolishly, I basically don’t use virtual
> destructors, and I do, quite causiously, use templates.
>
> The long and short of this is that, to be safe as possible, you have to
> look at complete map file, searching for the particulars, taking in to
> account the base class issue. This is very difficult, as well as time
> consuming, so I have to really, really want something to do it. I have
> written a tool (or modified an existing tool) that does, reliably, it
> seems, process images using the symbols to verify that particular
> instances of this problem are not occuring. This, of course, only works
> by my specifying accurately and without fail, what it should look for.
>
> I don’t imagine this helped very much, but this is, unfortunately, the
> best I have to offer. The best source of information I can point you to
> on this, is the documentation for DriverWorks, if you have access to it.
> I, presumably, may not include or note it, due to licensing issues.
> And, finally, as noted above, the product, well, sucks. The long and
> short is that, using these features of C++ (not to mention exception
> handling), needs to be carefully weighed against the potential downside.
> In my case, which is, I think, unusual, I find it to be worth it.
>
> MM
>

>> To my experience, templates are always placed in a non paged segment.
I

> would like to see sample code that proves otherwise. Besides, this
may
> depend on the compiler version. What was a problem in VC6 may no
longer
> apply in VC7.

I haven’t any. Personally, I would take the man’s word that this
indeed does occur, especially since all three of us seem to agree on, at
least, the fact the problem is in someway non-deterministic (Doron says
ND; I say Halting; you note that it is compiler dependent).

> The solution is to use __forceinline, the “inline only those marked
as
> inline” switch, and to make sure the relevant warnings are enabled
> (“function selected for inline expansion”, “function not inlined”
etc)

There are a large number of circumstances under which even a function
marked with __forceinline will not be inlined. Many of these can safely
and reasonably be avoided (i. e. - recursion) ; some can not. In my
mind, the most significant limitation, and I see it, for my purposes, as
crippling, is that a virtual function that is not called directly will
not be inlined. You are correct that the compiler is supposed to issue
a warning (and, morever, a warning that is very unlikely to be
suppressed by switches, unless you are pretty much looking for trouble).
However, in my mind, this is basically guaranteed to occur in anything
I write that is significant enough to me that I am actually willing to
take these sorts of risks. You’re milage may, of course, vary. Also, I
know that I would have very little chance of anticipating this problem.
The compiler will find it, but, by then, you may a serious problem
reworking your design. The other one that is just a deal breaker for me
is that, by default, debug build disable this. Obviously, this can be
prevented 100% of the time by not using -Ob0, but, in my opinion, at far
to large of a price: debugging. Not even close to worth it, in my mind.
Some of the other (documented) issues, I’m not entirely sure what they
mean in all cases, which troubles me. For example, does inability to
mix exception handling types refer to the immediate caller, or the
entire call chain (including library functions). You may know the
answer to this; I do not, although I would bet quite a bit that is has
to refer to the more limited case. Finally, this may sound paranoid,
but this is a relatively new feature to the compiler, and, as such, one
that I would be vary of relying on to the documentation to be 100%
complete to the extent that I would, essentially, not look for it were
problems to occur.

> To my experience, constructors and destructors should (a) always be

> explicitly defined, and (b) defined non-paged in .cpp. The compiler
is free
> to put an implicitly generated function to wherever it wants.

This is, in my opinion, just incorrect. You will not feel that way if
an implicitly defined destructor in a base class, such as a vector
deletion, appears in the wrong order and causes code to end up in a
pageable section. This is, in my opinion, not at all easy to predict,
and very difficult to diagnose, particuarly if you use some else code in
your hierarchy without knowing whether the destructor is virtual or
not.

MM

>> xxxxx@cristalink.com 2006-04-23 18:32 >>>
>The problem with templates is that the #pragmas around them do not
apply

To my experience, templates are always placed in a non paged segment. I

would like to see sample code that proves otherwise. Besides, this may

depend on the compiler version. What was a problem in VC6 may no longer

apply in VC7.

>ULONG GetCount(VOID) { return m_Count; }

The solution is to use __forceinline, the "inline only those marked as

inline" switch, and to make sure the relevant warnings are enabled
(“function selected for inline expansion”, “function not inlined”
etc).

>destructors

To my experience, constructors and destructors should (a) always be
explicitly defined, and (b) defined non-paged in .cpp. The compiler is
free
to put an implicitly generated function to wherever it wants.

Cheers

“Doron Holan” wrote in message
news:xxxxx@ntdev…
The problem with templates is that the #pragmas around them do not
apply. Where the code is instantiated is a non deterministic. I
worked
on a failed project that used templates in a driver where the section
in
which the generated code for a template moved from build to build
depending on minor changes elsewhere in the binary. It would blow up
at
random spots where code was not supposed to be pageable, but it was.
Basically, the only workaround is to have a completely non pageable
driver.

As for virtual destructors, the gotcha here is that the linker remove
identical functions. Many classes virtual destructor is the exactly
the
same code so you see only one or two of them that are shared in the
entire class hierarchy. The pageability of this function is not a
criteria for uniqueness so you can get a virtual desctructor that
should
be NP put in a pageable section. Templates make this worse b/c of the
even more randomness of the section that they generate code in.

Note that this does not apply only the desctructors but any function.
Another likely candidate are accessor functions like this

ULONG GetCount(VOID) { return m_Count; }

Where m_Count’s offset is 0x4. Any other accessor function which
returns a ULONG where the field resides at offset 0x4 will share the
function implementation even though they are not in the same class.
This also has the nasty side affect of making callstacks look very
strange and can lead to some initial false positives, such as

Bar::~Bar()
Foo::DestroySelf()
Foo::RunDown()

Where ~Bar() is a virtual destructor and where ~Foo() matches it, so
the
compiler just uses ~Bar() instead of ~Foo().

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of cristalink
Sent: Sunday, April 23, 2006 1:45 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Placement new operator in a driver

Can you be more specific, please? Can you provide any example of a
templated
function placed in a paged segment? What was the problem with virtual
destructors?

Thanks



“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
> This is definitely true. I learned about this one and the related
> problem of virtual destructors in the hardest of possible ways.
That
> being said, while there are very real constraints on what you can
safely
> do, and you really, really must either understand them or being
willing
> to suffer until you do, I still use aspects of C++ in the kernel,
mostly
> because I like to.
>
>
>
>>>> xxxxx@microsoft.com 2006-04-22 13:13 >>>
> You can get 1) and 2) just by using a .cpp file and then using C
BTW.
> /W4 also gets you most of the way in C.
>
>> However I came accross a memory optimization problem, when I add an
> object my template does something like :
>
> Please tell me you are not using templates. If you are don’t try to
> make any function pageable, otherwise the linker may place
templacized
> code in the wrong segment.
>
> d
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I agree with you conclusion (no thank you); your assertion that
everything goes to a non-pageable section, is, in my opinion, cleary not
true. I know that I have come across instances of it, which I
described; it sounds like Doron is saying similary things. If nothing
else, I mean, the INIT section does indeed exist. It may exist only by
default due to things occurring behind your back, but does that really
matter?

MM

>> xxxxx@cristalink.com 2006-04-23 19:05 >>>
According to my experience, all code, including templates, goes to a
default
segment, which is non-paged. If one starts to mess with autogenerated
code,
such as constructors, destructors, copy constructors etc, they are
looking
for troubles. There is not much point in having constructors or
destructors
paged, as they are usually short, at least my ones.

the documentation for DriverWorks, if you have access to it

No, thank you :slight_smile:

“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
>I haven’t looked at this problem in quite a while, as my experiences
> with them convinced me to avoid them where I was not willing to
check
> out the generated code extensively. I can give you an example for
> virtual destructors; not for templates (I explain why later). The
basic
> problem with virtual destructors is the same as that with templates:
> code can end up in pageable segments, which can (and generally will)
> cause problems that I’m sure your familiar with. The significant
> difference is that the manifestations of the case of virtual
destructors
> can be, to a significant extent, predicted and worked around. That
> being said, I rarely do so, as it is cumbersome, ugly, quite
possibly
> likely to break when the compiler changes, and, in the case of the
> kernel, avoidable by changing the representation. Normally, this is,
in
> my opinion, about the worst thing one can do; however, in this case,
the
> reasons are cogent. Unfortunately, as my principal motivation for
using
> C++ in the kernel (anywhere I roam, really) is templates, this is of
no
> help here.
>
> Please keep in mind that this is all empirical, and likely to change
> with the compiler.
>
> For every version of VC++ that I have looked at closely (which does
not
> include the most recent one, and, possibly the penultimate one as
well),
> the section in to which the code for a destructor is emitted depends
on
> whether it is virtual or not. In the case of a non virtual
destructor,
> the code (appears, at least) to go in to the same section as the
first
> code that references it; for the virtual case, it (again, appears) to
go
> in to the section that contains a reference to a constructor. The
> specific situation in which this causes a problem is when the first
> constructor (for a class with a virtual destructor) appears in the
INIT
> (or other discardable) section, and reference to the virtual
destructor
> occurs after it is discarded. The particularly nasty (and not
> automatably addresable) complication of this is that this will occur
if
> any of the classes base classes (if any) satisfy the same conditions
and
> appear in the INIT section. There is no reasonable way to ensure
that
> this does not occur, other than to avoid the use of virtual
destructors
> completely, or using the following, rather brutal hack, that, as I
> mentioned, I do not use (with a few specific exceptions that I have
> researched extensively; that being said, it is probably still not
the
> best idea, but rather one that I have gotten away with, and very
> possibly will be able to continue to do so, at least in the very
> meaningful sense (in my particular case, which is unusual, but,
> unfortunately, I may not describe)). Additional fun can be had
because
> the compiler will generate destructors for scalar and vector
deletion,
> and these, if unspecified and not worked around, will end up in INIT
> under the same conditions. OK, one more twist. The later only
occurs
> for checked builds.
>
> A work around to this, such as it is, is that to do the best you can
to
> ensure this issue, for any class that uses a virtual destructor, and
the
> at least one constructor for this class will occur in a pageable
section
> (under the conditions described above), you must create another
> constructor (that may just be empty) that appears in the same source
> module as the one that will appear in the INIT section, and it must
> occur before that constructor. As mentioned above, but reiterated
here
> because it is very easy to overlook, this is true for any class that
> derives from a class which contains a virtual destructor. If all of
> this sounds very suspect, I would tell you that it seems to work,
and
> then agree with you. The only confirmation, such as it is, that I
can
> offer you, is that I came up with this independently of DriverWorks
(but
> not, by a long shot, on my own), and we seem to agree. Normally,
this
> would be comforting; however, as has been pointed out many times in
this
> list (and I don’t think I have ever seen anyone disagree),
DriverWorks
> is a proverbial Piece of Shit, so I don’t know what this really
offers.
>
> I’m sorry, but I can not offer you a concrete example that I know
> exhibits it, because of the nature of the work in which I am
involved.
> This, however, is, to the best of my understanding and research,
> entirely accurate, including the part about it being labile.
>
> The situation for templates is much, much worse, in the sense of
being,
> without access to the source code for the compiler in question, there
is
> really no way (that I know of) to detail this conditions that
dictate
> where any piece of instantiated templated code might appear.
Formally,
> the whole issue is a Halting problem, and, as many such issues due,
> almost assuredly does have an answer, but not one that can be relied
> upon, unless, of course, you happen to know it. Ironically, and
some
> would, quite reasonably, say foolishly, I basically don’t use
virtual
> destructors, and I do, quite causiously, use templates.
>
> The long and short of this is that, to be safe as possible, you have
to
> look at complete map file, searching for the particulars, taking in
to
> account the base class issue. This is very difficult, as well as
time
> consuming, so I have to really, really want something to do it. I
have
> written a tool (or modified an existing tool) that does, reliably,
it
> seems, process images using the symbols to verify that particular
> instances of this problem are not occuring. This, of course, only
works
> by my specifying accurately and without fail, what it should look
for.
>
> I don’t imagine this helped very much, but this is, unfortunately,
the
> best I have to offer. The best source of information I can point you
to
> on this, is the documentation for DriverWorks, if you have access to
it.
> I, presumably, may not include or note it, due to licensing issues.
> And, finally, as noted above, the product, well, sucks. The long
and
> short is that, using these features of C++ (not to mention exception
> handling), needs to be carefully weighed against the potential
downside.
> In my case, which is, I think, unusual, I find it to be worth it.
>
> MM
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

“Martin O’Brien” wrote in message
news:xxxxx@ntdev…
> For example, does inability to
> mix exception handling types refer to the immediate caller, or the
> entire call chain (including library functions).

I don’t use exception handlers, apart from those for MmProbeAndLockPages or
similar. I don’t think it’s something very useful for kernel mode.

>> The compiler is free to put an implicitly generated function to wherever
>> it wants.

> This is, in my opinion, just incorrect. You will not feel that way if

To my knowledge, the relation between autogenerated code and the segment it
is placed in is not documented or defined in any standard (please correct me
if I am wrong here). Consequently, the compiler can put it anywere.You may
not like it (btw, I hate it), but this does not make that behavior
‘incorrect’, of course, if ‘incorrect’ is an opposite to ‘correct’, and the
latter is ‘conforming to an approved or conventional standard’
(Merriam-Webster’s definition).

>
> This is, in my opinion, just incorrect. You will not feel that way if
> an implicitly defined destructor in a base class, such as a vector
> deletion, appears in the wrong order and causes code to end up in a
> pageable section. This is, in my opinion, not at all easy to predict,
> and very difficult to diagnose, particuarly if you use some else code in
> your hierarchy without knowing whether the destructor is virtual or
> not.
>
> MM
>
>