473,890 Members | 1,370 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Confused about gcnew and object lifetime

I wanted to take advantage of the large set of functionality offered by
the framework, so for my latest project I'm using managed C++ with .NET
v2. I'm using the gcnew operator in two different ways, and I'm
confused about the lifetime of objects and whether or not I should be
calling delete. Here are two examples:

ref class SYMBOL : public IComparable
{
public:
// Constructor / destructor
SYMBOL()
{
name = nullptr;
};
~SYMBOL()
{
if (name != nullptr)
{
delete name;
}
}

//Data
String^ name;
UInt32 relativeAddress ;

// Methods
virtual Int32 CompareTo(Objec t^ obj)
{
MODULE^ mod = dynamic_cast<MO DULE^>(obj);

return relative.Compar eTo(mod->relativeAddres s);
}
};

In the example above, the class is used to create a List
(System.Collect ions.Generic.Li st) of SYMBOL objects. For each addition
to the list (symbols), I do a gcnew of a SYMBOL object, add pass the
gcnew'ed handle to the List.Add method. I also do a gcnew of a String
object, and assign the gcnew'ed handle to the name member of the SYMBOL
object. As you can see, I am explicitly deleting the String object in
the SYMBOL destructor. Is this correct?

The other case is this:

void PARSER::ReadLog File(void)
{
FileInfo^ logFileI = gcnew FileInfo(logFil ename);
FileStream^ logFileS = logFileI->OpenRead();
logData = gcnew array<Byte>((in t)logFileI->Length);
int bytesRead = logFileS->Read(logData , 0, (int)logFileI->Length);

delete logFileI;
// TODO: Add some error checking, mechanism for returning 0-length
array on error
}

As you can see, I'm manually deleting the gcnew'ed FileInfo. Is this
correct?

Sorry if this is a basic question, but the info I've found on the net
is not consistent. In one place I found an "expert" saying that
"objects created with gcnew should never be deleted." However, that
doesn't make sense to me. I understand that after the app exits,
objects on the managed heap will eventually be gc'ed, but to be
completely right about memory management, shouldn't I be deleting
objects that I create?

Thanks,
-Chris

Mar 20 '06
15 8341
Another example ... if I have a function like I have listed below, do I
need to delete each object returned from StreamReader.Re adLine? If I do
not delete each object, and I end up parsing a very large text file,
how will that affect the GC heap? Is the compiler / runtime smart
enough to see that I'm no longer storing a handle to the object (since
I've stored the handle of a new object in the original container), so
it eventually free's the objects even though the program is still
running (if it needs to do a gc)? Same line of question as previous
post ... if I want deterministic usage of the GC heap, is it safe (or
even proper) to go ahead and call delete on each object returned from
ReadLine?

Thanks,
-Chris

void MODULE::LoadSym bolTable(void)
{
StreamReader^ mapFile = gcnew StreamReader(fi lename);
String^ line;

while (line = mapFile->ReadLine())
{
// process the line
}

mapFile->Close();
delete mapFile;
}

Mar 21 '06 #11
Chris Edgington wrote:
For example, if I do { String^ newText = oldText->Remove(0,
someChars) }, is the API actually doing a gcnew of a String object,
and therefore is it now my responsibility to delete that object (or
leave it up to the GC to delete the object at some point).


Keep in mind - delete applied to a managed object does nothing unless the
object is IDisposable, in which case it calls Dispose() on it. For objects
like System::String, System::IO::Fil eInfo, etc., calling delete has no
effect whatsoever. The memory will be reclaimed only when the GC gets
around to it.

For an object such as System::IO::Fil eStream, which is IDisposable, calling
delete on it results in the unmanaged resources in controls being freed,
which is what you wanted.

-cd
Mar 21 '06 #12
Chris Edgington wrote:
Another example ... if I have a function like I have listed below, do
I need to delete each object returned from StreamReader.Re adLine?
No.
If
I do not delete each object, and I end up parsing a very large text
file, how will that affect the GC heap?
It will grow larger and eventually trigger a collect. This will be a Gen0
collect though, which is very fast.
Is the compiler / runtime
smart enough to see that I'm no longer storing a handle to the object
(since I've stored the handle of a new object in the original
container), so it eventually free's the objects even though the
program is still running (if it needs to do a gc)?
Yes. The CLR implements 100% accurate tracking of the reachability of
memory. The instant you assign a new value to line, the old value is
available for collection. Reachability is based on the concept of roots -
static variables are roots, as are all of the object references on the
stacks of all threads that have entered the CLR, plus any roots that have
been explicitly created (e.g. through the gcroot<T> template). If it's not
possible to reach an object by tracing references starting at a root then
the object is available for collection.
Same line of
question as previous post ... if I want deterministic usage of the GC
heap, is it safe (or even proper) to go ahead and call delete on each
object returned from ReadLine?
Safe and pointless. Since System::String isn't IDisposable, calling delete
on it will have no effect at all.

Thanks,
-Chris

void MODULE::LoadSym bolTable(void)
{
StreamReader^ mapFile = gcnew StreamReader(fi lename);
String^ line;

while (line = mapFile->ReadLine())
{
// process the line
}

mapFile->Close();
delete mapFile;
}


-cd
Mar 21 '06 #13
Wow. I'm from the device driver / embedded world, where you need to be
diligent about freeing even the smallest allocation. Your explanations
have answered all my questions, but also created many more. Are there
any books written on how this whole GC stuff works in the CLR?

As a side note - this almost seems like it would have the tendency to
create "sloppy" programmers - allocating objects willy nilly, depending
on the system to clean up. Or, maybe some would say that many
programmers are sloppy in the first place, and this type of system
exists to protect the platform from those programmers ;)

Thanks for the quick responses.

-Chris

Mar 21 '06 #14
Chris Edgington wrote:
As a side note - this almost seems like it would have the tendency to
create "sloppy" programmers - allocating objects willy nilly, depending
on the system to clean up.


In a system that was designed to handle that it's OK. It's a different
story when those programmers later go to an unmanaged environment,
whether they can adapt.

But even in the managed world, there are two issues with this "the
system will clean up for me" attitude. First, resources still need to be
manually disposed. Being sloppy there means scarce system resources may
remain locked indefinitely. Not closing a file is often not such a big
problem, but not closing a mutex is disastrous. IMO, it's not
immediately clear which object is a resource, and it puts an extra
pressure on the programmer. There's no quick way that I know of telling
whether an object needs deterministic destruction or not. GC makes
programmers sloppy in a way that they no longer care and may not even
deallocate resource type objects. This is a much bigger problem, as far
as I can tell, than being sloppy with memory allocations. In fact, in
..NET you can't deallocate memory, only the system can, but you still
MUST deallocate resources. In native C++ there is stack syntax that
always works, and boost::shared_p tr that always guards everything
properly. Ironically, .NET makes you think even harder than a C
programmer, because for every object allocated you have to look up the
help to decide whether it needs to be deleted or not. It makes me
paranoid -- did I miss something that really needs destruction? What
happens if a class doesn't store any resources today, but it may in the
future? That class will be used in 100s of places, without the proper
deallocation. Later a resource will be added for that class, and all of
a sudden every existing code becomes invalid. So classes that MAY behave
as a resoruce should be designed to be a resource from day 1. These
issues make you think just as hard as if you didn't have GC.

What's even worse is that .NET doens't have all the tools to make
guaranteed proper deletion of resources. The unmanaged world has slowly
evolved during the past several decades, and we finally have reference
counted smart pointers and deterministic destruction with very solid
guarantees and strong, stable libraries that really makes you forget
about manual deletion of everything. .NET was designed with the goal
that you no longer have to care about any of this stuff, which is not
entirely true. Maybe 99% of your objects never need to be deleted, but
that remaining 1% is as critical as ever was. So programmers still have
to be alert.

The second (completely different) aspect is that just because all memory
is guaranteed to be deleted it doesn't mean you can't have leaks
anymore. You can still have serious memory leaks even if all your
objects are always deterministical ly destructed. It's as simple as
forgetting about your items stored in containers. You no longer need
them, but they may still reside in some collection in the memory. If you
forget about removing unused objects from lists, maps, sets, hashed
storages, they occupy precious memory, and it's virtually the same
effect as a memory leak. Even worse, no memory leak detector ever finds
that. These kinds of problems are not automatically solved by any type
of garbage collection or reference counting. There's no magic solution
that enitrely protects the system from sloppy programmers.

Once I had a huge lookup table to speed up calculations, and I forgot to
make it a static member. So every instance of my classes had its own
copy of the table, and systems with 256MB RAM ran out of memory quickly.
No leak detector found anything, and yet my application's memory
consumption was growing well beyond the expected limits. Once again,
there was nothing that didn't get properly freed, and yet I had memory
issues due to a human error.

Tom
Mar 21 '06 #15
Chris Edgington wrote:
So maybe I didn't make it clear why I wanted the questions answered.
I'm not worried about running out of resources, and therefore wanting
to make sure that I'm explicility releasing them, I'm wanting to make
sure that resources aren't going to be GC'ed before I'm done with
them. I guess a better general question would be - does the GC ever
automatically release (delete) an object while the process owning the
object is still active?


You've unconvered a very interesting problem. Short answer is that the CLR
will never collect a managed object while before it has finished use. The
problem is when a managed object represents something else (like an OS file
handle, pointer to a buffer on the native heap, etc.) If the managed object
no longer has references to it, but the resource it manages is still being
used (because it didn't properly abstract the resource), the GC will collect
the manage object which will then clean up the resource.

For more info on this, check out:
http://blogs.msdn.com/cbrumme/archiv.../19/51365.aspx

To solve this in C++, just call delete on the handle to the managed object.
The call to destructor will keep the object alive until it is no longer
needed.

Cheerio!
Brandon
Mar 22 '06 #16

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

Similar topics

5
5490
by: Haoyu Zhang | last post by:
Dear Friends, Python assignment is a reference assignment. However, I really can't explain the difference in the following example. When the object is a list, the assignment seems to be a reference. However, when the object is a number, the story is so different. I don't understantd for what reason Python deals with them differently. The example is as follows: >>> a = >>> b = a
14
3175
by: MuZZy | last post by:
Hi, Lately i've been (and still am) fixing some memory leaks problems in the project i just took over when i got this new job. Among the other issues i've noticed that for localy created objects it makes difference to explicitly put them to null after working with them is done - it somehow makes the GC collect them sooner, like here: void SomeFunc() { MyClass c = new MyClass();
5
1647
by: Bit byte | last post by:
I have the following methods: static void Foo::setBar(const Bar*) ; //store a copy of Bar static const Bar* Foo::getBar(void) const ; //return an UNMODIFIABLE ptr to our internal copy In another part of my code , I retrieved and used Bar as follows: .... const Bar* temp = NULL ;
3
3172
by: hedbonker | last post by:
OK - I am new to .net C++. Trying to write a simple app that creates an XML output file based on some values that a user puts in a form. After looking in the help, the sample code provided was this: XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = (" "); using (XmlWriter writer = XmlWriter.Create("personal.xml", settings)) { // Write XML data.
0
1211
by: pkolinko | last post by:
Hi everyone, I am writing a small low level embedded USB application using C++/CLI windows Forms. I am sort of new to the C++/CLI and having trouble understanding what happens in this very simple line of code: I have a reference class pic_usbapi, declared in "pic_usbapi.h". I want to create an object of the class and have a tracking handle for it.
0
1198
by: whm | last post by:
The page http://msdn2.microsoft.com/en-us/708fb7c4(VS.80).aspx has this code: ServiceController^ sc = gcnew ServiceController; if ( sc ) { ... Section 15.4.6 in ECMA 372 (the C++/CLI spec) seems to indicate that gcnew either returns a handle to an object or it throws but the Microsoft-written code above seems to imply that gcnew could return
3
2348
by: nagashre | last post by:
class A { public: A():a(0), b(0){} handleMyMsg( char* aa, char*bb); private: processMessage();
1
458
by: dogbert1793 | last post by:
Hello, Does one need to delete pointers allocated with gcnew? Or does the garbage collector do it? I always though the garbage collector did it, but I saw this example today on MSDN: StreamReader^ sr = gcnew StreamReader( "TestFile.txt" ); try
6
2707
by: better_cs_now | last post by:
Hello all, class Foo {/* Details don't matter */}; class Bar { public: Bar(): m_Foo(/* Construct a Foo however it wants to be constructed */); const Foo &GetFoo() const { return m_Foo; } private:
0
9980
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9826
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11236
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10925
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
8018
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7172
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
6061
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4682
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4276
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.