473,404 Members | 2,114 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,404 software developers and data experts.

Why are destructors forbidden in __value types ?

I have a __value class which uses some legacy C++ code. So I wrapped the
legacy C++ code in another __nogc class and have a pointer to that class as
a member of my __value class. When the __value class is created, I
dynamically allocate an object of the class with the legacy C++ code.
However because the __value class has no destructor, I can never release
that allocated memory. Why does a __value class allow no destructor ?
Without it I can never mix code between __value and __nogc classes in a
single __value class situation. Is there a workaround for this silly
restriction ?
Nov 17 '05 #1
8 1784
Because the "destructor" of your value type would be the Finalize method
which will not be called for objects on the stack. The memory is freed as
soon as the function ends, no garbage collection necessary so Finalize won't
be called.

"Edward Diener" <ed******@tropicsoft.com> wrote in message
news:OX**************@TK2MSFTNGP10.phx.gbl...
I have a __value class which uses some legacy C++ code. So I wrapped the
legacy C++ code in another __nogc class and have a pointer to that class as a member of my __value class. When the __value class is created, I
dynamically allocate an object of the class with the legacy C++ code.
However because the __value class has no destructor, I can never release
that allocated memory. Why does a __value class allow no destructor ?
Without it I can never mix code between __value and __nogc classes in a
single __value class situation. Is there a workaround for this silly
restriction ?

Nov 17 '05 #2
Dirk wrote:
Because the "destructor" of your value type would be the Finalize
method which will not be called for objects on the stack. The memory
is freed as soon as the function ends, no garbage collection
necessary so Finalize won't be called.
To me, this is a weakness of .NET, that stack-based objects do not have
their destructors called.

As a workaround to this problem for a __value class, I will implement the
solution that when I need to use my legacy C++ code and functionality I will
have to allocate an object of that C++ class, call its functionality, and
then destroy the object each time. This is less elegant and more time
consuming than being able to create the object in the __value class's
constructor and destroy the object when the __value class is destroyed,
since the latter can never be tracked.

"Edward Diener" <ed******@tropicsoft.com> wrote in message
news:OX**************@TK2MSFTNGP10.phx.gbl...
I have a __value class which uses some legacy C++ code. So I wrapped
the legacy C++ code in another __nogc class and have a pointer to
that class as a member of my __value class. When the __value class
is created, I dynamically allocate an object of the class with the
legacy C++ code. However because the __value class has no
destructor, I can never release that allocated memory. Why does a
__value class allow no destructor ? Without it I can never mix code
between __value and __nogc classes in a single __value class
situation. Is there a workaround for this silly restriction ?

Nov 17 '05 #3
Edward Diener wrote:
I have a __value class which uses some legacy C++ code. So I wrapped the
legacy C++ code in another __nogc class and have a pointer to that class
as a member of my __value class. When the __value class is created, I
dynamically allocate an object of the class with the legacy C++ code.
However because the __value class has no destructor, I can never release
that allocated memory. Why does a __value class allow no destructor ?
Without it I can never mix code between __value and __nogc classes in a
single __value class situation. Is there a workaround for this silly
restriction ?


I can make some comments on the existing syntax, but I'll make the majority
of my comments about the new syntax being introduced with Visual Studio
Whidbey.

First, value types in the Frameworks are intended to be lightweight objects
that have no pressure on the garbage collector. In that sense, many
languages have even taken the tact of defining them as immutable. This is
especially important with boxing. The boxing operation does a bitwise copy
of the value type. If the value is holding on to a pointer to a native
class, then the appropriate action would be to ref count the number of
pointers. The boxing operation makes this impossible.

With the new C++ syntax, support for implicit boxing (much as many other
..NET languages already support) makes this issue all the more relevant. When
an object is on the heap, it is the users responsibility to call the
destructor. With implicit boxing, this is next to impossible. Another
language probably would not enforce those semantics, and even the C++ user
wouldn't know when to do that.

I could commit several more pages to this. In short, this really isn't a
silly restriction.

That said, the new syntax is trying to solve this a different way. We are
working to allow ref classes (these replace __gc classes) to have
destructors, and allow them to have lexical semantics (basically, they can
be allocated on the stack or embedded within other classes). Thus, ref
classes will allow you to write this kind of code and will be resilient even
in cross language scenarios.

Cheerio!

--
Brandon Bray http://blogs.gotdotnet.com/branbray/
This posting is provided AS IS with no warranties, and confers no rights.
Nov 17 '05 #4
Brandon Bray [MSFT] wrote:
Edward Diener wrote:
I have a __value class which uses some legacy C++ code. So I wrapped
the legacy C++ code in another __nogc class and have a pointer to
that class as a member of my __value class. When the __value class
is created, I dynamically allocate an object of the class with the
legacy C++ code. However because the __value class has no
destructor, I can never release that allocated memory. Why does a
__value class allow no destructor ? Without it I can never mix code
between __value and __nogc classes in a single __value class
situation. Is there a workaround for this silly restriction ?
I can make some comments on the existing syntax, but I'll make the
majority of my comments about the new syntax being introduced with
Visual Studio Whidbey.

First, value types in the Frameworks are intended to be lightweight
objects that have no pressure on the garbage collector. In that
sense, many languages have even taken the tact of defining them as
immutable.


What does holding lightweight object have to do with their being immutable
or not ? Do you mean to say that if they are immutable, then they wouldn't
need to be destroyed ?
This is especially important with boxing. The boxing
operation does a bitwise copy of the value type. If the value is
holding on to a pointer to a native class, then the appropriate
action would be to ref count the number of pointers. The boxing
operation makes this impossible.

With the new C++ syntax, support for implicit boxing (much as many
other .NET languages already support) makes this issue all the more
relevant. When an object is on the heap, it is the users
responsibility to call the destructor.
With implicit boxing, this is
next to impossible.
I didn't realize that boxed objects get their destructors ( finalizers )
called. If they do the limitation against __value classes having destructors
makes sense. If they did their destructors could be called multiple times.
Another language probably would not enforce those
semantics, and even the C++ user wouldn't know when to do that.

I could commit several more pages to this. In short, this really
isn't a silly restriction.

That said, the new syntax is trying to solve this a different way. We
are working to allow ref classes (these replace __gc classes) to have
destructors
They already do.
, and allow them to have lexical semantics (basically,
they can be allocated on the stack or embedded within other classes).
Sounds great, but that means you are going to call their destructors
eventually even when they are placed on the stack. That's fine with me.
Thus, ref classes will allow you to write this kind of code and will
be resilient even in cross language scenarios.


Good !

As a workaround for my problem, from within appropriate member functions of
my __value class I am allocating my native C++ class when I need to call any
of its functions and deleting it when I am through. Not as elegant as
allocating my native C++ class in the constructor and deleting it in a
destructor, but at least it works.
Nov 17 '05 #5
Edward Diener wrote:
What does holding lightweight object have to do with their being immutable
or not ? Do you mean to say that if they are immutable, then they wouldn't
need to be destroyed ?
If an object holds onto a resource, then it needs to have a finalizer. Once
an object needs to be finalized, it is no longer lightweight -- just having
them will lead to performance issues. Some languages have made them
immutable, thus making it impossible for them to hold onto resources.
I didn't realize that boxed objects get their destructors ( finalizers )
called.
Boxed value types never have their finalizers run. To the CLR, value types
don't have finalizers at all (even if it overrides the Finalize method).
If they do the limitation against __value classes having destructors
makes sense. If they did their destructors could be called multiple
times.
Finalizers and destructors are two different things. The existing managed
extensions syntax (and C#) make a great mess of things by confusing the two.
That said, the new syntax is trying to solve this a different way. We
are working to allow ref classes (these replace __gc classes) to have
destructors


They already do.


Actually, they don't. __gc classes have finalizers. They use the destructor
syntax for this unfortunately. This is being fixed in the new Whidbey
syntax.
As a workaround for my problem, from within appropriate member functions
of my __value class I am allocating my native C++ class when I need to
call any of its functions and deleting it when I am through. Not as
elegant as allocating my native C++ class in the constructor and deleting
it in a destructor, but at least it works.


If you're using value types, that's the only way to do it right. Value types
don't have destructors or finalizers, so holding onto resources outside of
function scope is very dangerous.

Cheerio!

--
Brandon Bray http://blogs.gotdotnet.com/branbray/
This posting is provided AS IS with no warranties, and confers no rights.
Nov 17 '05 #6
Brandon Bray [MSFT] wrote:
Edward Diener wrote:
What does holding lightweight object have to do with their being
immutable or not ? Do you mean to say that if they are immutable,
then they wouldn't need to be destroyed ?
If an object holds onto a resource, then it needs to have a
finalizer. Once an object needs to be finalized, it is no longer
lightweight -- just having them will lead to performance issues. Some
languages have made them immutable, thus making it impossible for
them to hold onto resources.


Everything was fine until your final sentence, which does not follow
logically from the first two even if it is true for some languages. Simply
because a lightweight object may hold a resource is no reason for making
them immutable. The word "may" or "does" are two different things in this
concept. As a conceptual analogy, "Simply because a human being may commit a
heinous offense is no reason for putting that person in jail."
I didn't realize that boxed objects get their destructors (
finalizers ) called.
Boxed value types never have their finalizers run. To the CLR, value
types don't have finalizers at all (even if it overrides the Finalize
method).


Then there is no reason to restrict __value types so that they can not have
destructors, other than that the CLR does not want to track value types when
they go out of scope in order to call their destructors at that time.
If they do the limitation against __value classes having destructors
makes sense. If they did their destructors could be called multiple
times.
Finalizers and destructors are two different things. The existing
managed extensions syntax (and C#) make a great mess of things by
confusing the two.


I realize that they are syntactically different but the natural situation
for languages that do have destructors is for the destructor to be called
once the finalizer method is called. That is what C# and MC++ does, and I
think this is an excellent decision. The greatest weakness of Java compared
to .NET is that Java has no destructors or any guarantee of a destructor
being finally called, but .NET actually does have destructors which are
called throug the finalizer method. Of course both are flawed as GC
languages in their inability for implementing the optimum way to deal with
classes which encapsulate resources, despite Dispose() and Close() and other
workarounds, but at least .NET makes an attempt at some solutions, by
supporting destructors, while Java does not.
That said, the new syntax is trying to solve this a different way.
We are working to allow ref classes (these replace __gc classes) to
have destructors
They already do.


Actually, they don't. __gc classes have finalizers. They use the
destructor syntax for this unfortunately. This is being fixed in the
new Whidbey syntax.


The biggest improvement that could be made in the Whidbey release, or any
further .NET release, is a simple idea although it may be difficult
presently to implement: allow certain classes and certain objects to be
marked ( I favor a "resource" attribute ) in such a way that when the object
goes out of scope, the runtime checks immediately to see whether the
destructor can be called ( no other references ) and does call it if it can.
This is the ultimate solution to handling resource objects, and would
entirely eliminate the headaches posed by them in .NET. Until MS takes this
simple stance in their GC language, it will remain partially flawed in a way
that other GC based languages are also flawed. Once MS does implement the
above, or its equivalent, .NET will standout from current flawed
implementations of GC in other languages. But it is up to MS to implement
this instead of procrastinating and looking for further future kludges,
similar to Dispose(), Close(), and other poor workarounds.
As a workaround for my problem, from within appropriate member
functions of my __value class I am allocating my native C++ class
when I need to call any of its functions and deleting it when I am
through. Not as elegant as allocating my native C++ class in the
constructor and deleting it in a destructor, but at least it works.


If you're using value types, that's the only way to do it right.
Value types don't have destructors or finalizers, so holding onto
resources outside of function scope is very dangerous.


Yes, I figured this out. Still that is only because the run-time is
unwilling to track when value types go out of scope. If I could mark my
value type using something like the "resource" attribute suggested above,
then I should be able to have a finalizer and wouldn't have to have the
inelegant workaround which I do. I can live with the workaround for the
present, but I encourage MS to solve this problem as previously noted for
the future.
Nov 17 '05 #7
Edward Diener wrote:
Brandon Bray [MSFT] wrote:
If an object holds onto a resource, then it needs to have a
finalizer. Once an object needs to be finalized, it is no longer
lightweight -- just having them will lead to performance issues. Some
languages have made them immutable, thus making it impossible for
them to hold onto resources.


Everything was fine until your final sentence, which does not follow
logically from the first two even if it is true for some languages.
Simply because a lightweight object may hold a resource is no reason
for making them immutable. The word "may" or "does" are two different
things in this concept. As a conceptual analogy, "Simply because a
human being may commit a heinous offense is no reason for putting
that person in jail."


Then you have an argument with the designers of those languages which have
made value types immutable. MC++ does not, nor does C# nor the CLR itself.
Boxed value types never have their finalizers run. To the CLR, value
types don't have finalizers at all (even if it overrides the Finalize
method).


Then there is no reason to restrict __value types so that they can
not have destructors, other than that the CLR does not want to track
value types when they go out of scope in order to call their
destructors at that time.


But that's one of the primary purposes of value types in the CLR - the lack
of any need to track their lifetimes and call their finalizer/destructor.
Sure, the CLR could have been defined differently, but it wasn't.
Actually, they don't. __gc classes have finalizers. They use the
destructor syntax for this unfortunately. This is being fixed in the
new Whidbey syntax.


The biggest improvement that could be made in the Whidbey release, or
any further .NET release, is a simple idea although it may be
difficult presently to implement: allow certain classes and certain
objects to be marked ( I favor a "resource" attribute ) in such a way
that when the object goes out of scope, the runtime checks
immediately to see whether the destructor can be called ( no other
references ) and does call it if it can. This is the ultimate
solution to handling resource objects, and would entirely eliminate
the headaches posed by them in .NET. Until MS takes this simple
stance in their GC language, it will remain partially flawed in a way
that other GC based languages are also flawed. Once MS does implement
the above, or its equivalent, .NET will standout from current flawed
implementations of GC in other languages. But it is up to MS to
implement this instead of procrastinating and looking for further
future kludges, similar to Dispose(), Close(), and other poor
workarounds.


C++/CLI in the Whidbey release will solve this problem once and for all for
C++ developers on .NET, and in a way that's CLS compliant and natural for
C++ developers Note that this is a compiler solution, not a CLR solution -
afterall, the compiler already has all the information to know which objects
have destructors/finalizers to run - it merely needs to emit the necessary
IL to do it.

-cd
Nov 17 '05 #8
Carl Daniel [VC++ MVP] wrote:
Edward Diener wrote:

The biggest improvement that could be made in the Whidbey release, or
any further .NET release, is a simple idea although it may be
difficult presently to implement: allow certain classes and certain
objects to be marked ( I favor a "resource" attribute ) in such a way
that when the object goes out of scope, the runtime checks
immediately to see whether the destructor can be called ( no other
references ) and does call it if it can. This is the ultimate
solution to handling resource objects, and would entirely eliminate
the headaches posed by them in .NET. Until MS takes this simple
stance in their GC language, it will remain partially flawed in a way
that other GC based languages are also flawed. Once MS does implement
the above, or its equivalent, .NET will standout from current flawed
implementations of GC in other languages. But it is up to MS to
implement this instead of procrastinating and looking for further
future kludges, similar to Dispose(), Close(), and other poor
workarounds.


C++/CLI in the Whidbey release will solve this problem once and for
all for C++ developers on .NET, and in a way that's CLS compliant and
natural for C++ developers Note that this is a compiler solution,
not a CLR solution - afterall, the compiler already has all the
information to know which objects have destructors/finalizers to run
- it merely needs to emit the necessary IL to do it.


That is magnificent news to hear, but it means that other .NET languages
must still use the Dispose/Close paradigm and its inherent kludginess. It
also means that a programmer using .NET C++ components will program
different from a programmer not using .NET C++ components, thus damaging the
basic idea in .NET of language interoperability at the CLS level.

That surely can not be MS's intention, to solve the problem for a single
language and not for .NET in general. What is needed in the CLS
specification is that any .NET language can enable the programmer to mark
classes and/or objects in such a way that a particular instantiated object
can have its destructor/finalizer called whenever that object goes out of
scope and there are no further references on that object. In other words
solve the problem in .NET once and for all, by allowing programmers to mark
a class as being one that must be deterministically destroyed, and by
allowing them to mark an object in the same way. Then the whole issue of
allowing a mix of GC and non-GC classes and objects, necessary for resources
and other areas of deterministic destruction, would be solved much to the
greater glory of .NET.

I know, this will be "considered for some time in the future", and I know
that MS is aware of the problem. But if MS with all their technical
expertise can't solve this problem, then the computing world is in big
trouble no matter what propaganda is churned from the mills of MS or Sun
regard the importance of garbage collection as a programming idiom.
Nov 17 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: Edward Diener | last post by:
Is there a way to override the default processing of the assignment operator for one's own __value types ? I realize I can program my own Assign method, and provide that for end-users of my class,...
3
by: Edward Diener | last post by:
In the doc regarding __value classes, under Primitive Types, I read: "Generally, the C++ types and their __value class equivalents are interchangeable in Managed Extensions." What exactly does...
0
by: Edward Diener | last post by:
Why is there a prohibition of instantiating __value type enums and classes within __nogc classes ? After all __value types are not managed by the GC and built-in __value types, such as 'int', are...
15
by: Edward Diener | last post by:
Why is it impossible to have a __value class instance variable in a __nogc class when it is possible to have a built-in type instance variable in a __nogc class ? __value class X { int a; };...
5
by: PaulW | last post by:
Personally, I like to use simple abstractions to wrap resources For example consider a class that wraps a resource - say an IntPtr which is allocated in the constructor and deallocated in the...
0
by: Marcus Kwok | last post by:
I have been reading through the ManagedExtensionsSpec.doc file and I thought something was not clear. If I have a __value class (really a __value struct but that shouldn't make a difference) and...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.