Placement new operator in a driver

Hi all,

My question for today is for people who do C++ in drivers. In my project I
developed an object oriented linked list (amongst other things) to replace
the existing linked list present in the DDK (I have my reasons, main one
being nevrosis). It works. However I came accross a memory optimization
problem, when I add an object my template does something like :

NTSTATUS AddEntry(T **ppAddedEntry, T *pToAdd)
{

T *pNewEntry = new T(pToAdd)

// linked list chaining stuff and about 700 lines of ASSERT()

*ppAddedEntry = pNewEntry;

return STATUS_SUCCESS;

}

Don’t worry, my driver has got specific new and delete operator that will
take the memory from paged pool or non paged pool (depending on the object).

I told to myself : “wait, won’t it be more efficient to use a lookaside list
to allocate memory for all the entries of the list since they have the same
size and might be very small omg this sentence is long”. So I did that. But
if I allocate the memory this way, the constructor of the object will not be
called which is of course a problem.

“No problem!” says I “I’ll use a placement new”, then I did that :

NTSTATUS AddEntry(…)
{

void *pMemory = static_cast*>(ExAllocateLookAsideListOptimizationOmgOmg(…))

// …

T *pNewEntry = new(pMemory)T();

}

And now the compiler doesn’t like me anymore and tells me awful things like
“there is no new which takes two arguments” and “I was faking”.

Is there no support for placement new operator in the DDK or is it me who
missed something? It works 100% with the former method but I thought look
aside lists could have a positive effect on memory usage.

Thanks for your help.



Edouard

> “No problem!” says I “I’ll use a placement new”, then I did that :

I’ve used placement new with no problem to select between paged and
non-paged pool.

You wrote a class private operator new with placement parameters, right?

  • 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:

Edouard

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

“No problem!” says I “I’ll use a placement new”, then I did that :

I’ve used placement new with no problem to select between paged and
non-paged pool.

You wrote a class private operator new with placement parameters, right?

  • 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


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.

A global placement new can be defined as follows:

void * __cdecl operator new(size_t size, void *location)
{
return location;
}

This works for me. I don’t see why your class placement new didn’t work. You
did actually implement the class placement new somewhere, right?

=====================
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 Edouard A.
Sent: Saturday, April 22, 2006 6:12 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Placement new operator in a driver

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:

Edouard

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

> “No problem!” says I “I’ll use a placement new”, then I did that :

I’ve used placement new with no problem to select between
paged and non-paged pool.

You wrote a class private operator new with placement
parameters, right?

  • 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



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

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:

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

> 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

Unfortunately I will not have access to the code until Monday, you’ll have
to wait until then. I hope you will sleep well nonetheless. :wink: My guts now
tell me I’ve missed something obvious.

EA

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

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


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.

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.

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

>
It is not necessary to use C++ in a driver at all. It is really a question
of the underlying design principle used. Are you sticking to pure OO /
generics or just plain old Win32 API style C design. The language is a means
to capturing the larger design principles.

<>
Let me explain this with an example. One of the important design principles
I would want is inheritance + delegation. As long as the language I use
allows me to capture this with ease, its good for development. However, if
for some reason, you are comfortable with design that doesnt warrant
generalization/ composition, C should be good.

<>
Having said this, I believe, this language war is eye wash. You can capture
most semantics of C++ or any OO language like eiffel, smalltalk in C by
using an IDL compiler. It takes in one CFG and spits out another , eos. What
does that mean? The Vtable can be captured in C using either compile time
constructs for e.g.,
struct A INHERITSFROM struct B where INHERITSFROM is a macro that expands to
the necessary underlying vtable manipulation or you could use a runtime OO
hierarchy like Java, e.g,
+createRelation ( struct_name, struct_base )
+struct_name *object createObject( struct_name , input parameters)

<>
The advantage of using runtime semantics like this is heavy type checking
but a higher overhead at runtime. The former is cool/sleak but type unsafe.
The third option is to catch hold of a IDL compiler. The IDL compiler just
takes as input a design warrant THATS IT!! It parses this and spits out
language dependent code. This is very popular in distributed computing CORBA
where different languages/compilers are used for implementation but they all
speak the same OO language, viz., OO design. Check out the IDL compiler
SLICE at http://www.zeroc.com/languages.html

<>
IMHO C++ as of now, is a pretty weak language for capturing most of OO
semantics. In any caseI like to strongly distinguis b/w generics and pure
OO. They conflict heavily. OO = data and methods manipulating data should
stay together. Generics = methods separate but can work on different data.

banks

“MM” wrote in message news:xxxxx@ntdev…
> 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
>>
>>
>

> Curious, but what is the purpose of C++ in a driver? Other than added

problems such as this, why?

There is no requirement to use placement new, so this isn’t really a
problem, it’s more how do I get a better way to work.

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?

Everything also can be done in assembler, so why do you deal with all the
hassles of a C compiler?

I personally use C++ in drivers because my experience is the benefits are
much greater than the problems. A quick example, I have a little class
called ReferenceCounted, which adds an integer counter and an AddRef and
UnRef method to every class I add it to. I also have a template class
ReferenceCountedPtr which makes a smart pointer to any class that
inherits from ReferenceCounted. What this does for me is it moves all
reference counting code into a very localized bit of code, instead of spread
all over my driver. I use my ReferenceCountedPtr pretty much like a normal
pointer, except I don’t have to write any explicit code to manage the
reference count. I also have little classes called Linked (for objects that
will be put in lists), SpinLocked (for objects that need to be spinlocked),
and ObjectMetaData (which supplies a bunch of methods mostly for debugging,
like ToString). The automatic reference counting looks like this:

// 14 lines
Void myfunc(void)
{
ReferenceCountedPtr ptr;

ptr = new AClass(1,2,3);
if (ptr) {
passObjectToSomething(ptr);
}

ptr = new AClass(4,5,6);
if (ptr) {
passObjectToSomething(ptr)
}
}

The above code does NOT leak memory, and the objects are deleted when they
are no longer used. The first AClass allocated may or may not get freed when
the assignment of the second AClass happens. The second AClass may or may
not get freed when the function returns (ptr goes of scope). The equivalent
C code would be:

// 28 lines
Void myfunc(void)
{
AClass * ptr;

ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(AClass), TAG_ACLASS);
if (ptr) {
constructAClass(ptr);
InterlockedIncrement(&(ptr->refCount));
ptr->virtualFunctions->create(ptr, 1,2,3);
passObjectToSomething(ptr);
if (InterlockedDecrement(&(ptr->refCount)) == 0) {
ptr->virtualFunctions->destructor(ptr);
ExFreePoolWithTag(ptr, TAG_ACLASS);
}
}

ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(AClass), TAG_ACLASS);
if (ptr) {
constructAClass(ptr);
InterlockedIncrement(&(ptr->refCount));
ptr->virtualFunctions->create(ptr, 4,5,6);
passObjectToSomething(ptr);
if (InterlockedDecrement(&(ptr->refCount)) == 0) {
ptr->virtualFunctions->destructor(ptr);
ExFreePoolWithTag(ptr, TAG_ACLASS);
}
}
}

This is 28 lines of code I would have to write in C vs 14 in C++. In
general, I find I get something like a 2x savings in source lines. Unless
you believe I can write/debug C twice as fast as I can write/debug C++, then
this seems like a real gain in developer productivity.

Encapsulation also seems much more flexible in C++. I can define a class
member function, and easily switch it between virtual, non-virtual, and
__forcedinline. If I write C code, I can’t offhand think of any syntax that
lets me adjust the implementation of a called function so easily. Like this:

aLocal = anObject->GetValue(); // this is the call to GetValue

I could then define:

virtual int GetValue(void) {return property1;};

or

int GetValue(void) {return property1;};

or

__forcedinline int GetValue(void) {return property1;};

The ease of encapsulation is interrelated to ease of polymorphism. In C, I
could write a function AClass_GetValue(Class * obj) and switch it between
inline or not, but I can’t switch it from say the inline access of a member
variable to a polymorphic function call, without changing the source code of
every call. I suppose I could change ACLASS_GetValue to the right stuff for
a polymorphic call, but then my source code basically says:

AClass_GetValue(obj); // this actually may be calling BClass_GetValue

This causes namespace expansion, because as a programmer I now have to know
there is AClass_GetValue and BClass_GetValue, instead of just GetValue. As
things get more complex it also becomes AClass_GetValue, BClass_GetValue,
CClass_GetValue, DClass_GetValue, DClass_GetValue instead of just a single
GetValue. From a programmer point of view, C keeps my THINKING in terms of
concrete implementation selection instead of abstract operation selection.

In C++, I can just change the definition, and my source code keeps the nouns
(the objects) and the verbs (the function selector) distinct. For example,
every one of my classes has a member function ToString() which I know will
give something appropriate for a trace message. The default implementation
in the lowest base class just returns a sting with the class name and
address. Some classes return strings with more complex information. The
simple case programming cost for me to do this is in every class I define:

Class myClass {
OBJECT_META_DATA(“myClass”);
}

I’m not saying you can’t do much of this in C, my point is its less work to
let the C++ compiler do the work. The binary has pretty much equivalent
functionality, but the C++ source code is simpler and smaller, just like the
C source is smaller and simpler than assembler source would be.

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

I’ve never used DriverWorks. I can’t say I’ve tried to write a driver
framework that does everything a driver developer might want for every kind
of driver.

I’ve been writing drivers in C++ for a number of years now, and still find
every C++ based driver I write is better structured than the last one, so I
must still be learning. There have been MANY common elements, and it would
have been nice if those came predefined, in source form. Using C++ tends to
add a bit of overhead at the beginning of the project, but then as the
project moves forward a LOT of things are just much easier.

For intellectual property ownership reasons, I can’t just take previous
class I’ve written for a different company and use them. I can just write
the classes again, which goes super fast since some of them I’ve written
over and over. A minus is, I have to write essentially the same class over
and over, a plus is I get to write it better each time. The last couple of
projects I’ve heavily used multiple inheritance (after being inspired by one
of the DDK multimedia samples), and the benefits clearly outweigh the
occasional head scratching.

I probably need to learn about using C++ combined with KMDF and UMDF.

- Jan

Not to get involved in another c/c++ debate, but this is the kicker for
me

the benefits clearly outweigh the occasional head scratching.

It is the head scratching that I worry about, esp for the poor soul who
has to inherit the code that was written after you are done with it. Or
even, worse, the 3rd guy who has no connection to me. Maintenance of
the code I generate is very important to me b/c it is going to live for
a very very long time (as I would assume it is for lots of folks).

I am very big on anyone being able to read the code and see what is
going on in an obvious way. 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.

Smart pointers/RAII classes do have their place, I am not arguing that.
I just think that in the code I write, they should be limited in scope
to very specific cases and that their role and actions are obvious upon
first glance by the reader.

d

– 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: Saturday, April 22, 2006 8:19 PM
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?

There is no requirement to use placement new, so this isn’t really a
problem, it’s more how do I get a better way to work.

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?

Everything also can be done in assembler, so why do you deal with all
the
hassles of a C compiler?

I personally use C++ in drivers because my experience is the benefits
are
much greater than the problems. A quick example, I have a little class
called ReferenceCounted, which adds an integer counter and an AddRef and
UnRef method to every class I add it to. I also have a template class
ReferenceCountedPtr which makes a smart pointer to any class that
inherits from ReferenceCounted. What this does for me is it moves all
reference counting code into a very localized bit of code, instead of
spread
all over my driver. I use my ReferenceCountedPtr pretty much like a
normal
pointer, except I don’t have to write any explicit code to manage the
reference count. I also have little classes called Linked (for objects
that
will be put in lists), SpinLocked (for objects that need to be
spinlocked),
and ObjectMetaData (which supplies a bunch of methods mostly for
debugging,
like ToString). The automatic reference counting looks like this:

// 14 lines
Void myfunc(void)
{
ReferenceCountedPtr ptr;

ptr = new AClass(1,2,3);
if (ptr) {
passObjectToSomething(ptr);
}

ptr = new AClass(4,5,6);
if (ptr) {
passObjectToSomething(ptr)
}
}

The above code does NOT leak memory, and the objects are deleted when
they
are no longer used. The first AClass allocated may or may not get freed
when
the assignment of the second AClass happens. The second AClass may or
may
not get freed when the function returns (ptr goes of scope). The
equivalent
C code would be:

// 28 lines
Void myfunc(void)
{
AClass * ptr;

ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(AClass), TAG_ACLASS);
if (ptr) {
constructAClass(ptr);
InterlockedIncrement(&(ptr->refCount));
ptr->virtualFunctions->create(ptr, 1,2,3);
passObjectToSomething(ptr);
if (InterlockedDecrement(&(ptr->refCount)) == 0) {
ptr->virtualFunctions->destructor(ptr);
ExFreePoolWithTag(ptr, TAG_ACLASS);
}
}

ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(AClass), TAG_ACLASS);
if (ptr) {
constructAClass(ptr);
InterlockedIncrement(&(ptr->refCount));
ptr->virtualFunctions->create(ptr, 4,5,6);
passObjectToSomething(ptr);
if (InterlockedDecrement(&(ptr->refCount)) == 0) {
ptr->virtualFunctions->destructor(ptr);
ExFreePoolWithTag(ptr, TAG_ACLASS);
}
}
}

This is 28 lines of code I would have to write in C vs 14 in C++. In
general, I find I get something like a 2x savings in source lines.
Unless
you believe I can write/debug C twice as fast as I can write/debug C++,
then
this seems like a real gain in developer productivity.

Encapsulation also seems much more flexible in C++. I can define a class
member function, and easily switch it between virtual, non-virtual, and
__forcedinline. If I write C code, I can’t offhand think of any syntax
that
lets me adjust the implementation of a called function so easily. Like
this:

aLocal = anObject->GetValue(); // this is the call to GetValue

I could then define:

virtual int GetValue(void) {return property1;};

or

int GetValue(void) {return property1;};

or

__forcedinline int GetValue(void) {return property1;};

The ease of encapsulation is interrelated to ease of polymorphism. In C,
I
could write a function AClass_GetValue(Class * obj) and switch it
between
inline or not, but I can’t switch it from say the inline access of a
member
variable to a polymorphic function call, without changing the source
code of
every call. I suppose I could change ACLASS_GetValue to the right stuff
for
a polymorphic call, but then my source code basically says:

AClass_GetValue(obj); // this actually may be calling BClass_GetValue

This causes namespace expansion, because as a programmer I now have to
know
there is AClass_GetValue and BClass_GetValue, instead of just GetValue.
As
things get more complex it also becomes AClass_GetValue,
BClass_GetValue,
CClass_GetValue, DClass_GetValue, DClass_GetValue instead of just a
single
GetValue. From a programmer point of view, C keeps my THINKING in terms
of
concrete implementation selection instead of abstract operation
selection.

In C++, I can just change the definition, and my source code keeps the
nouns
(the objects) and the verbs (the function selector) distinct. For
example,
every one of my classes has a member function ToString() which I know
will
give something appropriate for a trace message. The default
implementation
in the lowest base class just returns a sting with the class name and
address. Some classes return strings with more complex information. The
simple case programming cost for me to do this is in every class I
define:

Class myClass {
OBJECT_META_DATA(“myClass”);
}

I’m not saying you can’t do much of this in C, my point is its less work
to
let the C++ compiler do the work. The binary has pretty much equivalent
functionality, but the C++ source code is simpler and smaller, just like
the
C source is smaller and simpler than assembler source would be.

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

I’ve never used DriverWorks. I can’t say I’ve tried to write a driver
framework that does everything a driver developer might want for every
kind
of driver.

I’ve been writing drivers in C++ for a number of years now, and still
find
every C++ based driver I write is better structured than the last one,
so I
must still be learning. There have been MANY common elements, and it
would
have been nice if those came predefined, in source form. Using C++ tends
to
add a bit of overhead at the beginning of the project, but then as the
project moves forward a LOT of things are just much easier.

For intellectual property ownership reasons, I can’t just take previous
class I’ve written for a different company and use them. I can just
write
the classes again, which goes super fast since some of them I’ve written
over and over. A minus is, I have to write essentially the same class
over
and over, a plus is I get to write it better each time. The last couple
of
projects I’ve heavily used multiple inheritance (after being inspired by
one
of the DDK multimedia samples), and the benefits clearly outweigh the
occasional head scratching.

I probably need to learn about using C++ combined with KMDF and UMDF.

- 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

Loren, is there native built-in support for C++ in the kernel enviro.?
Does this mean you have to add your own support?
The more code one writes, will there be a higher probability that a bug
will be lurking?
C was easy to learn - not following you on that point…

What does assembler have to do with a discussion about C vs, C++?

m

Loren Wilton wrote:

>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

>

the only real influence on software quality is the person behind the
keyboard.

True with all applications; I would just ask, why are all of OSR’s
samples, DDK samples, and MS core
components written in C? I’ll just leave it at that…

Very talented people put all of those things together…

m

“Unless you believe I can write/debug C twice as fast as I can write/debug C++, then
this seems like a real gain in developer productivity.”

“developer productivity” - One of those management phrases… When I hear this, I think
of Larry the Cable Guy - “Get err done”.

Good arguments though, I enjoyed reading your input. I would agree with
Doron’s point about other people trying to
interpret your code.

m.

Jan Bottorff wrote:

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

There is no requirement to use placement new, so this isn’t really a
problem, it’s more how do I get a better way to work.

>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?
>
>

Everything also can be done in assembler, so why do you deal with all the
hassles of a C compiler?

I personally use C++ in drivers because my experience is the benefits are
much greater than the problems. A quick example, I have a little class
called ReferenceCounted, which adds an integer counter and an AddRef and
UnRef method to every class I add it to. I also have a template class
ReferenceCountedPtr which makes a smart pointer to any class that
>inherits from ReferenceCounted. What this does for me is it moves all
>reference counting code into a very localized bit of code, instead of spread
>all over my driver. I use my ReferenceCountedPtr pretty much like a normal
>pointer, except I don’t have to write any explicit code to manage the
>reference count. I also have little classes called Linked (for objects that
>will be put in lists), SpinLocked (for objects that need to be spinlocked),
>and ObjectMetaData (which supplies a bunch of methods mostly for debugging,
>like ToString). The automatic reference counting looks like this:
>
>// 14 lines
>Void myfunc(void)
>{
>ReferenceCountedPtr ptr;
>
> ptr = new AClass(1,2,3);
> if (ptr) {
> passObjectToSomething(ptr);
> }
>
> ptr = new AClass(4,5,6);
> if (ptr) {
> passObjectToSomething(ptr)
> }
>}
>
>The above code does NOT leak memory, and the objects are deleted when they
>are no longer used. The first AClass allocated may or may not get freed when
>the assignment of the second AClass happens. The second AClass may or may
>not get freed when the function returns (ptr goes of scope). The equivalent
>C code would be:
>
>// 28 lines
>Void myfunc(void)
>{
>AClass * ptr;
>
> ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(AClass), TAG_ACLASS);
> if (ptr) {
> constructAClass(ptr);
> InterlockedIncrement(&(ptr->refCount));
> ptr->virtualFunctions->create(ptr, 1,2,3);
> passObjectToSomething(ptr);
> if (InterlockedDecrement(&(ptr->refCount)) == 0) {
> ptr->virtualFunctions->destructor(ptr);
> ExFreePoolWithTag(ptr, TAG_ACLASS);
> }
> }
>
> ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(AClass), TAG_ACLASS);
> if (ptr) {
> constructAClass(ptr);
> InterlockedIncrement(&(ptr->refCount));
> ptr->virtualFunctions->create(ptr, 4,5,6);
> passObjectToSomething(ptr);
> if (InterlockedDecrement(&(ptr->refCount)) == 0) {
> ptr->virtualFunctions->destructor(ptr);
> ExFreePoolWithTag(ptr, TAG_ACLASS);
> }
> }
>}
>
>This is 28 lines of code I would have to write in C vs 14 in C++. In
>general, I find I get something like a 2x savings in source lines. Unless
>you believe I can write/debug C twice as fast as I can write/debug C++, then
>this seems like a real gain in developer productivity.
>
>Encapsulation also seems much more flexible in C++. I can define a class
>member function, and easily switch it between virtual, non-virtual, and
>__forcedinline. If I write C code, I can’t offhand think of any syntax that
>lets me adjust the implementation of a called function so easily. Like this:
>
>aLocal = anObject->GetValue(); // this is the call to GetValue
>
>I could then define:
>
>virtual int GetValue(void) {return property1;};
>
>or
>
>int GetValue(void) {return property1;};
>
>or
>
>__forcedinline int GetValue(void) {return property1;};
>
>The ease of encapsulation is interrelated to ease of polymorphism. In C, I
>could write a function AClass_GetValue(Class * obj) and switch it between
>inline or not, but I can’t switch it from say the inline access of a member
>variable to a polymorphic function call, without changing the source code of
>every call. I suppose I could change ACLASS_GetValue to the right stuff for
>a polymorphic call, but then my source code basically says:
>
>AClass_GetValue(obj); // this actually may be calling BClass_GetValue
>
>This causes namespace expansion, because as a programmer I now have to know
>there is AClass_GetValue and BClass_GetValue, instead of just GetValue. As
>things get more complex it also becomes AClass_GetValue, BClass_GetValue,
>CClass_GetValue, DClass_GetValue, DClass_GetValue instead of just a single
>GetValue. From a programmer point of view, C keeps my THINKING in terms of
>concrete implementation selection instead of abstract operation selection.
>
>In C++, I can just change the definition, and my source code keeps the nouns
>(the objects) and the verbs (the function selector) distinct. For example,
>every one of my classes has a member function ToString() which I know will
>give something appropriate for a trace message. The default implementation
>in the lowest base class just returns a sting with the class name and
>address. Some classes return strings with more complex information. The
>simple case programming cost for me to do this is in every class I define:
>
>Class myClass {
> OBJECT_META_DATA(“myClass”);
>}
>
>I’m not saying you can’t do much of this in C, my point is its less work to
>let the C++ compiler do the work. The binary has pretty much equivalent
>functionality, but the C++ source code is simpler and smaller, just like the
>C source is smaller and simpler than assembler source would be.
>
>
>
>>Driver Works is proof drivers shouldn’t be written in C++ (of all their
>>developers and dollars, they never got it right).
>>
>>
>
>I’ve never used DriverWorks. I can’t say I’ve tried to write a driver
>framework that does everything a driver developer might want for every kind
>of driver.
>
>I’ve been writing drivers in C++ for a number of years now, and still find
>every C++ based driver I write is better structured than the last one, so I
>must still be learning. There have been MANY common elements, and it would
>have been nice if those came predefined, in source form. Using C++ tends to
>add a bit of overhead at the beginning of the project, but then as the
>project moves forward a LOT of things are just much easier.
>
>For intellectual property ownership reasons, I can’t just take previous
>class I’ve written for a different company and use them. I can just write
>the classes again, which goes super fast since some of them I’ve written
>over and over. A minus is, I have to write essentially the same class over
>and over, a plus is I get to write it better each time. The last couple of
>projects I’ve heavily used multiple inheritance (after being inspired by one
>of the DDK multimedia samples), and the benefits clearly outweigh the
>occasional head scratching.
>
>I probably need to learn about using C++ combined with KMDF and UMDF.
>
>- 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
>
>
>

What matters is what tool is right for *you*. If you prefer C, by all means
use it.

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

Loren, is there native built-in support for C++ in the kernel enviro.?
Does this mean you have to add your own support?
The more code one writes, will there be a higher probability that a bug will
be lurking?
C was easy to learn - not following you on that point…

What does assembler have to do with a discussion about C vs, C++?

m

Loren Wilton wrote:

>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


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.

> 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

Edouard, is what matters to *you*, what tool is right for *you*?

“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.
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of MM
> Sent: Sunday, April 23, 2006 13:38
> To: Windows System Software Devs Interest List
> Subject: Re: [ntdev] Placement new operator in a driver
>
> Loren, is there native built-in support for C++ in the kernel enviro.?
> Does this mean you have to add your own support?
> The more code one writes, will there be a higher probability that a bug
> will
> be lurking?
> C was easy to learn - not following you on that point…
>
> What does assembler have to do with a discussion about C vs, C++?
>
> m
>
>
> Loren Wilton wrote:
>
>>>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
>>
>>
>>
>
> —
> 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.
>
>
>
>
>

What matters is the *right* tool for the job. Without the right tool,
the job can’t be done right. If you know C++,
you sure as hell know C.

m

Edouard A. wrote:

What matters is what tool is right for *you*. If you prefer C, by all means
use it.

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

Loren, is there native built-in support for C++ in the kernel enviro.?
Does this mean you have to add your own support?
The more code one writes, will there be a higher probability that a bug will
be lurking?
C was easy to learn - not following you on that point…

What does assembler have to do with a discussion about C vs, C++?

m

Loren Wilton wrote:

>>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
>
>
>
>
>


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