Is There Any Reason to Even Use VC++ Anymore?

B

Brian Muth

Peter Oliphant said:
Sure:

http://msdn2.microsoft.com/en-us/library/xey702bw(en-us,VS.80).aspx

Quote on this page ("This syntax" refers to C++/CLI syntax):

"This syntax replaces the previous syntax, known as Managed Extensions for
C++. Managed Extensions for C++ syntax is are still available, but as a
deprecated feature under /clr:blush:ldSyntax compiler option."

You have cleverly edited out the statement you made: "MS has aggresively
announced they won't support my code in the near future..."

That was the statement I was wondering if you could back up with a link. I
assume not.

Brian
 
J

Josh McFarlane

Peter said:
Yes, I still have backups of the 2003 version, and I could use them. BUT -
MS has announced that 'gc' has been deprecated. So, if I continue to use
2003 MS has aggresively announced they won't support my code in the near
future...

Honestly why use gc at all? Never got why people felt the need for a
garbage collector.

Sometimes you just have to update things for a number of reasons. All
of the sprintf and buffer copy functions were also declared depreciated
because MS introduced more secure versions (most of the time it just
involved adding _s to the call and letting the compiler handle the
rest)
 
P

Peter Oliphant

You have cleverly edited out the statement you made: "MS has aggresively
announced they won't support my code in the near future..."

That was the statement I was wondering if you could back up with a link. I
assume not.

No, I didn't cleverly edit anything out. You ASKED for a link to support my
statement, I gave you a link to support my statement. If there was some
particular aspect of my statement that you want me to address, then you
should have made this clear (which obviously you didn't, and still haven't).
Anyway...

The link I gave has a quote by MS stating that Managed C++ (old syntax) is
deprecated. That was my point, that something that MS released just 2 years
ago is now deprecated. Do you deny this?

But, your right. MS didn't say they would just stop supporting MY CODE in
the future, they said they would stop supporting MANY PEOPLE'S CODE in the
future (i.e., those that bought into old syntax Managed C++).

[==P==]
 
P

Peter Oliphant

Honestly why use gc at all? Never got why people felt the need for a
garbage collector.

I will assume you mean this in general, not specifically 'gc'. As such, I'll
answer you question in regards to why the concept of garbage-collected
classes is a good thing...

The basic problem has to do with ownership. A class is passed a pointer to
an instance of something created externally to it. Simple right? Not really!
Who is responsible for destroying this instance? Well, if the instance is
only to be used by the class, then the class can destroy it when its done
with it. But, if the instance still has usage outside the class, it should
not be destroyed by the class! But if the instance is not used outside the
class, then it should be destroyed by the class, or else you get a memory
leak (memory allocated which is never freed up).

Now, how can the class know whether the instance has further use externally?
Answer: in general, it can't! A class, is typically unaware of the
environment it is in, since many classes are designed for re-usability in
DIFFERENT environments.

An example. Say a class is responsible for displaying the color of an object
representing a toy ball. It does this by taking a pointer to a ball object
and displaying its color. Now, here's the problem. The caller could have
passed a pointer to the instance of the ball itself, or a COPY of this
instance. In the first case, the instance should not be destroyed. In the
second case, the instance passed MUST be destroyed. But the class has no
idea which case is true for any particular call!

Garbage collecting solves this problem since its aware of the ENTIRE
application. Thus, it keeps track of who is using objects, and destroys
those it discovers nowbody is using anymore. It does this by keeping track
of references to the object. A reference is (usually) generated every time a
pointer to the object is created. When the number of these references drops
to zero 'nobody' has any idea the object even exists anymore (since nobody
has a reference to it), and so the GC systen can safely destroy it.

[==P==]
 
J

Josh McFarlane

Peter said:
Now, how can the class know whether the instance has further use externally?
Answer: in general, it can't! A class, is typically unaware of the
environment it is in, since many classes are designed for re-usability in
DIFFERENT environments.

Contracts between the calling function and the destination functions
work quite nicely for me.

If I require an object in a function, I use a reference.

If, for some reason, the object needs to be worried about the life of
the object (Such as a "message" being passed), I make that a condition
of the function if it is the end-point and destroy the object.

If, for another reason, the calling function needs to allocate memory,
call a 2nd function, and then is done with the memory, it is up to the
calling function to remove the memory from play.
An example. Say a class is responsible for displaying the color of an object
representing a toy ball. It does this by taking a pointer to a ball object
and displaying its color. Now, here's the problem. The caller could have
passed a pointer to the instance of the ball itself, or a COPY of this
instance. In the first case, the instance should not be destroyed. In the
second case, the instance passed MUST be destroyed. But the class has no
idea which case is true for any particular call!

If the function is responsible for drawing the ball, it should be up to
the caller function to determine whether or not the allocated object is
through. I mean granted it's around for another cycle or two until you
hit the delete function, but the cost is negligible.

I tend to shun away from using lists of pointers, and generally don't
have that big of a problem with it. I just go with the philosophy of
the allocator owns the pointer, unless it calls another function which
always assumes ownership of the allocated pointer, and that the owner
is responsible for freeing the memory.

Can you give an example where memory would have to be allocated prior
to the function, but the function would require both pass-through and
delete functionality that the calling function could not provide?
 
C

Carl Daniel [VC++ MVP]

Josh McFarlane said:
Honestly why use gc at all? Never got why people felt the need for a
garbage collector.

IME there's only one BIG advantage to a GC: it will automatically collect
cycles, while other lifetime management systems (like reference counting)
won't. A lesser advantage of GC is that gen-0 allocation and collection is
very efficient (orders of magnitude faster than a traditional malloc()-like
implementation). But if you don't keep most of your objects in gen-0, this
benefit can be completely overshadowed by the high cost of gen-1 and gen-2
collection.

I general, I agree with your sentiment: By making appropriate use of RAII
(using smart pointers, etc), it's possible (nee, easy) to write native C++
that has no memory leaks at all. I don't think I've had a memory leak in
any native C++ code I've written in the last 5 years or more.

-cd
 
P

Peter Oliphant

Contracts between the calling function and the destination functions
work quite nicely for me.

I've used this method to, and it's pretty good. It works fine if I'm the
only one creating the code. However, getting a team to adhere to this
rigorously is prone to error. And this is complicated due to what I think is
a bug in the new VS C++.NET 2005 (Express). I reported it here:

http://lab.msdn.microsoft.com/produ...edbackid=ef3c8d9e-75e2-4916-87ee-640a4de75f39

Turns out if you use a reference (or value) parameter in a method that only
accepts a pointer it will still compile! Thus, the convention of using a
pointer if you own it and a reference if owned externally is broken (not
your fault!) since both a pointer and a reference are accepted by a method
asking for a pointer! I hope this isn't considered a 'feature' by MS...
I tend to shun away from using lists of pointers, and generally don't
have that big of a problem with it.

How do you deal with variable length lists? Imagine a picture editor. Would
you set a limit as to how many pictures can be editted at a time, and keep
all instances of them around regardless of how many you will actually need?
It is probably better to keep a dynamic list of pointers to each of the
pictures being editted. This extends to many situations where the
application can't know ahead of time how many of something it will need,
especially if this number is only limited by available memory or dictated
by the end-user...
I just go with the philosophy of
the allocator owns the pointer, unless it calls another function which
always assumes ownership of the allocated pointer, and that the owner
is responsible for freeing the memory
Can you give an example where memory would have to be allocated prior
to the function, but the function would require both pass-through and
delete functionality that the calling function could not provide?

I'll try. Consider this scenario. A is created. A creates X (allocation). B
is created. B shares X (not a duplicate). What should B do when it is
destroyed? It doesn't know if A still exists, so it can't destroy X. But if
A HAS already been destroyed, then when B is destroyed there is nothing left
to destroy X, so X becomes a memory leak.

Note that A is the allocator of X, but can't be the destroyer if A goes away
before B. And B can't be the destroyer, since it doesn't know if A is still
around when B is destroyed. And even if B somehow knows A has already been
destroyed, B doesn't know if A also shared X with C. If B destroys X and C
exists, C will complain. If B doesn't destroy X and C doesn't exist, X
becomes a memory leak. And what about the possiblity of the existence of
other sharer's of X such as D, E, F. G, H,...?

Only at the application level can it be determined that there is NOTHING in
the application still using X, and so the application is the only thing that
can safely destroy X. That, in a nutshell, is garbage collection! : )

[==P==]
 
J

Josh McFarlane

Peter said:
How do you deal with variable length lists? Imagine a picture editor. Would
you set a limit as to how many pictures can be editted at a time, and keep
all instances of them around regardless of how many you will actually need?
It is probably better to keep a dynamic list of pointers to each of the
pictures being editted. This extends to many situations where the
application can't know ahead of time how many of something it will need,
especially if this number is only limited by available memory or dictated
by the end-user...

Containers of objects. Granted, I have to sometimes have buffers that
are pointers to char arrays, can't get around that, but they're stored
in a vector of char*s for the program's document / similar class, and
maintained by the controler, rather than the called function / window
and delete'ed as the "closed" command is initiated from the window.
(Also tells the editor window depending on it to shut down and waits
for it to terminate before deleting the buffer pointer.
I'll try. Consider this scenario. A is created. A creates X (allocation). B
is created. B shares X (not a duplicate). What should B do when it is
destroyed? It doesn't know if A still exists, so it can't destroy X. But if
A HAS already been destroyed, then when B is destroyed there is nothing left
to destroy X, so X becomes a memory leak.

OK, the one thing I can think of is a shared memory space between two
processes. However, can the garbage collector know what another process
is not using said shared memory space?

Otherwise, you have two possible scenarios from this:

A is called in Thread Foo, allocates X and launches thread B.
If both access the allocated X you've got syncronization problems
already, but the safe side would be that under the assumption that B
was doing processing on X, you'd have to have some way to notify the
main application that processing was done, and that could be done by
posting a message, and that message handles management during results
Note that A is the allocator of X, but can't be the destroyer if A goes away
before B. And B can't be the destroyer, since it doesn't know if A is still
around when B is destroyed. And even if B somehow knows A has already been
destroyed, B doesn't know if A also shared X with C. If B destroys X and C
exists, C will complain. If B doesn't destroy X and C doesn't exist, X
becomes a memory leak. And what about the possiblity of the existence of
other sharer's of X such as D, E, F. G, H,...?

But then you have to ask yourself why do D, E, F, G, H need X data past
the point of when A returns?
Only at the application level can it be determined that there is NOTHING in
the application still using X, and so the application is the only thing that
can safely destroy X. That, in a nutshell, is garbage collection! : )

Avoiding the multi-threading issue of allowing the pointers, and
focusing on single threading for now (Feel free to let me know if you
want to discuss the multi-threading aspect of it), how do you have A be
destroyed before B - H are finished with their processing of the
pointer? If you're using the pointers for anything more than
read-conditions, you have a race issue if you're handling them with an
indeterminate order. If you are simply using them for constant reads,
why not simply make it linking to a const reference in an STL container
in the document or form?

I've just always had the view that the garbage collector is there to
allow developers to have to maintain less of a hold over their
variables. Don't worry about tracking that race condition down, it'll
all delete itself in the end.

Maybe I'm just used to all my variables having a very clear distinct
allocation time (smallest being inter-function, and longest being in
the constructor / destructor of the main window itself) who knows.
 
D

Dave

I general, I agree with your sentiment: By making appropriate use of RAII
(using smart pointers, etc), it's possible (nee, easy) to write native C++
that has no memory leaks at all.

Carl, can you recommend any good docs on RAII as you're using it?

BTW, I think a major plus in garbage collection is the fact that it
cleans up code and makes it easier to maintain. Even if programmers
are fastidious in memory allocation, that takes some effort, and the
resulting code is often not transparent.
 
D

David Wilkinson

Dave said:
Carl, can you recommend any good docs on RAII as you're using it?

BTW, I think a major plus in garbage collection is the fact that it
cleans up code and makes it easier to maintain. Even if programmers
are fastidious in memory allocation, that takes some effort, and the
resulting code is often not transparent.

Dave:

If you use smart pointers and the standard library, then RAII just
happens. I don't think garbage collection makes things any easier. And
of course RAII is not just for memory management anyway.

To be fair, I think the primary goal of .NET is to produce verifiably
safe code, and C++ with RAII cannot provide that (unfortunately).

What bothers me, though, is that the CLI seems to have been modeled
after Java rather than C++. This IDisposable stuff rather than automatic
RAII is just absurd. The one good thing about the Managed C++ fiasco is
that it provided the opportunity to break with C# and implement the
destructor and the finalizer in C++/CLI the way they should always have
been.

Although C++/CLI is a big improvement, it still has to deal with the
muddled CLI object model, tacked on top of the very clean C++ one.

David Wilkinson
 
A

Andre Kaufmann

Josh said:
[...]
Contracts between the calling function and the destination functions
work quite nicely for me.

But over DLL boundaries you can't pass objects and ownership directly.
And if you have to share code with different languages you have to use
DLLs.
[...]
have that big of a problem with it. I just go with the philosophy of
the allocator owns the pointer, unless it calls another function which
always assumes ownership of the allocated pointer, and that the owner
is responsible for freeing the memory.
[...]


And if there are multiple owners ? E.g. if the object is stored in
multiple lists ? How to keep track of ownership ?

I use reference counting in native C++, managed code does this
"automatically" ;-)

Andre
 
J

Josh McFarlane

Andre said:
But over DLL boundaries you can't pass objects and ownership directly.
And if you have to share code with different languages you have to use
DLLs.

So the GC can see past code that isn't in it's realm, such as native or
VB, or even a shared memory space, or am I confusing what you're trying
to say?

[...]
have that big of a problem with it. I just go with the philosophy of
the allocator owns the pointer, unless it calls another function which
always assumes ownership of the allocated pointer, and that the owner
is responsible for freeing the memory.
[...]
And if there are multiple owners ? E.g. if the object is stored in
multiple lists ? How to keep track of ownership ?

Never had a reason to have multiple ownership. For items that have
program-lifetime, I handle initialization before spawning whatever else
needs it, still own it, and then deconstruct / destroy it at program
shutdown after the dependant objects are destroyed.

Can you give a concrete example of a variable lifetime for an object
dealt with by 2 different threads that doesn't have an inherant race
condition?

Josh McFarlane
 
P

Peter Oliphant

Never had a reason to have multiple ownership.

That's quite possible, since what is required for any particualr application
varies greatly.

Consider, though, if you were a 3D game programmer who wanted to invent an
engine to rival DirectX (I know, blasphemy, I tell you, blasphemy! :) You
realize one of the tricks is to have some texture that can be repeated on
multiple walls in the world.

Does it make sense to have each wall object keep a separate copy of the
texture? Even today this would cause the computer and/or graphics to run out
of memory fast. It is better for each wall object to point to the same
bitmap representing the texture. However, you want to support the broadest
base of possibly machines, so you want to dump textures no longer being used
to reduce end-user memory requirements. Part of the scheme should then
include that if an object needs a texure not already in memory it loads it
in. Fair enough?

In this scenario, a wall could easily discover it needs to load in its
texture, and then future walls could make use of it. But the wall that
loaded it in could easily be destroyed while other walls are still making
use of it. So the allocator can't be the destructor.

Ok, then who does destroy the texture when everyone is done with it? Well,
one clever method might be for the allocator to designate to another wall
still using the texture that it be the 'torch carrier' for destroying the
texture. Then when a wall discovers there are no more walls using it, it
might destroy the texture. This is a bit cumbersome, but could be done using
'static' variables to comunicate amongst the walls. Quick note: Notice how
this method requires GLOBALIZING information amongst the walls...

So, when the 'torch carrier' wall can't find another wall to pass the torch
to, it destroys the texture. But wait!!!! We want this application to be
REALLY efficient, so we cleverly allow that same texture to be usable by
other objects in the world: like furniture, posters, helmets, flags, etc. So
now none of the walls in the wall class can destroy the texture, since it is
necessary to know when no object in the system is still using it. Now we
need to derive everything that could use the texture from one class. Gee,
this is getting even more cumbersome, and even more GLOBAL in scope.
Especially since we just used up all our 'inheritance cards' (multiple
inheitance is not universally supported, such as VS.NET CLI). For example,
now you can't have a derived custom Form class that uses the texture since
no class can derive from both our 'texture-aware' underlining class AND Form
at the same time. Bummer.

So, stepping outside the box, and realizing that the entity responsible for
destroying our texture benefits form being as global as it can be, we see
that the best candidate for keeping track of whether or not any object is
still using the texture is the application itself, since it has the largest
scope for the application (DUH!). And when the application takes care of
destroying things that are no longer being used, this is called 'garbage
collecting"! : )

Yes, of course there are ways around these techniques that don't require GC.
Just like there are ways of doing Windows programming in assembly, or
avoiding object-oriented techniques such as creating classes. One could wrap
the allocation/delete methods, keep track of everything allocated and how
many references to each, and destroy anything not already destroyed upon
exit. But that would be just writing your own GC! Why not instead just use
all the tools available to you if they make life easier?

[==P==]

PS - Josh - how would you do the above texture situation WITHOUT maving
multiple ownership of the texture bitmap in memory?



Josh McFarlane said:
Andre said:
But over DLL boundaries you can't pass objects and ownership directly.
And if you have to share code with different languages you have to use
DLLs.

So the GC can see past code that isn't in it's realm, such as native or
VB, or even a shared memory space, or am I confusing what you're trying
to say?

[...]
have that big of a problem with it. I just go with the philosophy of
the allocator owns the pointer, unless it calls another function which
always assumes ownership of the allocated pointer, and that the owner
is responsible for freeing the memory.
[...]
And if there are multiple owners ? E.g. if the object is stored in
multiple lists ? How to keep track of ownership ?

Never had a reason to have multiple ownership. For items that have
program-lifetime, I handle initialization before spawning whatever else
needs it, still own it, and then deconstruct / destroy it at program
shutdown after the dependant objects are destroyed.

Can you give a concrete example of a variable lifetime for an object
dealt with by 2 different threads that doesn't have an inherant race
condition?

Josh McFarlane
 
A

Andre Kaufmann

Josh said:
Andre Kaufmann wrote:
[...]
So the GC can see past code that isn't in it's realm, such as native or
VB, or even a shared memory space, or am I confusing what you're trying
to say?

I meant implementing a function returning an object in VB.NET and using
the object in C#. With native code you have to use handles or COM
interfaces wrapping the object. Using the object directly is IMHO easier
than dealing with handles.

And if there are multiple owners ? E.g. if the object is stored in
multiple lists ? How to keep track of ownership ?

Never had a reason to have multiple ownership. For items that have
program-lifetime, I handle initialization before spawning whatever else
needs it, still own it, and then deconstruct / destroy it at program
shutdown after the dependant objects are destroyed.

Josh has given a good example in the other thread, I'll try to give one too:

Example:

You have a thread with a list of objects, let's say objects handling
files. In another thread (mustn't be a thread by the way) you are
selecting some of these and copy the reference to another list, to do
some operations on the files.

After the operation has succeeded you remove them one by one from the
second list. If you have reference counted or managed objects you simply
can discard the object. If not you have to check the first list, if the
object is still inside and if you have to delete it or not.
Can you give a concrete example of a variable lifetime for an object
dealt with by 2 different threads that doesn't have an inherant race
condition?

I don't see one. You have to protect the reference pointer when copied,
to ensure that the object isn't deleted before the other thread has
taken the ownership. And for sure the methods and resources itself.
For managed objects that means you have to protect (eventually) the
dispose method to be called multiple times from different threads, but
that's the price you have to pay if you want / have to use multiple threads.

And as I wrote already, multiple ownership doesn't mean necessarily that
multiples threads must be involved. I find it quite handy to have
reference pointers to an object in multiples list and don't have to care
if it's still used but only have to remove the reference pointer from
the object list.

Doesn't mean that I use reference counting / GC for all of my objects. ;-)
Josh McFarlane

Andre
 
G

Guest

From a purely language feature perspective does C++ offer more than C#? For
example are templates more powerful than generics?

Basically, I am trying to determine if C# is to C++ as C++ was to C. I.e.
C++ basically replaced C except for specialized things such drivers/embedded
systems development. Has C# basically replaced C++ (except for such things as
native Windows development etc.) as the name C# (C++++) implies?

Should I switch to C# and basically just use C++ only when strictly needed?
With your answer could you please include an overall YES/NO to this question
so we can tally up the YESes vs. the NOs and see what the general consensus
is.

My vote is YES. C# has replaced C++ except for cases when C++ is 'required".
 
A

aa

Greg said:
From a purely language feature perspective does C++ offer more than C#?
For
example are templates more powerful than generics?

Basically, I am trying to determine if C# is to C++ as C++ was to C.

They're not even related, C#, a pale shadow of C++, is a Microsoft invention
primarily intended to support application development in the Windows
environment.

C++ offers templates, classes and is portable to most operating systems.
Write in C++; run in Windows. Write in C#; run it only in Windows.
 
B

Bo Persson

Greg said:
From a purely language feature perspective does C++ offer more than
C#? For
example are templates more powerful than generics?

They are not related. :)

Templates do their work at compile time. Generics is a run-time
concept. In that sense C++ offers something that C# doesn't have.
Basically, I am trying to determine if C# is to C++ as C++ was to C.
I.e.
C++ basically replaced C except for specialized things such
drivers/embedded
systems development. Has C# basically replaced C++ (except for such
things as
native Windows development etc.) as the name C# (C++++) implies?

To me, C# is to C++ as Java was to C++.
Should I switch to C# and basically just use C++ only when strictly
needed?

You should definitely use C++ when needed. :)
With your answer could you please include an overall YES/NO to this
question
so we can tally up the YESes vs. the NOs and see what the general
consensus
is.

I bet the result will be "No concensus". :)
My vote is YES. C# has replaced C++ except for cases when C++ is
'required".

It depends on how you determine when it is required.

You can count me as a NO.



Bo Persson
 
J

Josh McFarlane

Peter said:
Never had a reason to have multiple ownership.
[Snipped Texture Memory Allocation Example]

Kudos on that example, never dealt with 3D Rendering so never had that
issue to deal with I'll have to get back to you once I let it rumble
around in my brain for a little bit. =)

Josh McFarlane
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top