I still have many problems with correct cleaning up ressources. When analyzing the problems I came accross that already in VO the source code was not always correct (the source code that I had written on my own or that I had collected from different programmers). Here is what I have understood until now:
VO:
- Registeraxit (self) tells the garbage collector that an own method AXIT must be called to clean up additional ressources as file handles, SQL objects, ... that are not standard dynamic memory variables as strings, objects....
- In case that a close method called from the program calls "Unregisteraxit(self)" then the AXIT method does not have to be called anymore because all cleaning has already been made.
- UnregisterAxit in the AXIT method does not make any sense because unregisteraxit should be used to avoid calling AXIT
DOTNET:
- RegisterAxit is not needed, having a destructor (previous AXIT) is sufficient for the runtime to know that there is a method to be called for cleaning.
- The destructor is not similar to the C++-destructor and should only be used if necessary. It should only clean up ressources like file handles, SQL objects.
- the destructor needs additional ressources and prevents cleaning up objects quickly when having to call the destructor. Therefore similar to VO UnregisterAxit(self) or gc.suppressfinalizer(self) can be called in a close method called from the program.
- In contrast to VO the DOTNET garbage collector is called in another program thread parallel to the program execution. This makes the program execution much faster, but can give errors if ressource usage as ODBC is not threadsafe or when accessing global objects.
- Microsoft recommends using the IDISPOSABLE interface for cleaning up ressources. This seems to be mainly for having implementation rules and does not resolve directly correct cleaning up of ressources.
VO and DOTNET:
- Both, VO and Dotnet, have advantages if close methods are called by the programmer if possible: Ressources are released immediately, runtime errors in the close method appear in the normal thread and can be detected easier.
- Both, VO and Dotnet have advantages to limit access to external ressources like files/databases to few program parts and try to handle logical processess only using standard variables as string/objects.
Gargage Collector and VO->X#-Conversion
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Gargage Collector and VO->X#-Conversion
Arne,
I am not sure if there was a question in your message ...
Some remarks:
- In .Net RegisterAxit is not needed. The function in the Vulcan Runtime is empty. DESTRUCTOR (Finalize) is called automatically
- UnRegisterAxit() in .Net calls GC.SuppressFinalize() internally.
- Indeed in .Net the Dispose pattern is recommended. In that case you call GC.SuppressFinalize() in the Dispose method.
- Destructors in .Net are difficult to do right. Ms says about this:
Finalizers are notoriously difficult to implement correctly, primarily because you cannot make certain (normally valid) assumptions about the state of the system during their execution
....
For example, a finalizable object A that has a reference to another finalizable object B cannot reliably use B in A’s finalizer, or vice versa. Finalizers are called in a random order (short of a weak ordering guarantee for critical finalization).
Also, be aware that objects stored in static variables will get collected at certain points during an application domain unload or while exiting the process. Accessing a static variable that refers to a finalizable object (or calling a static method that might use values stored in static variables) might not be safe if Environment.HasShutdownStarted returns true.
See more info on https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx
Robert
I am not sure if there was a question in your message ...
Some remarks:
- In .Net RegisterAxit is not needed. The function in the Vulcan Runtime is empty. DESTRUCTOR (Finalize) is called automatically
- UnRegisterAxit() in .Net calls GC.SuppressFinalize() internally.
- Indeed in .Net the Dispose pattern is recommended. In that case you call GC.SuppressFinalize() in the Dispose method.
- Destructors in .Net are difficult to do right. Ms says about this:
Finalizers are notoriously difficult to implement correctly, primarily because you cannot make certain (normally valid) assumptions about the state of the system during their execution
....
For example, a finalizable object A that has a reference to another finalizable object B cannot reliably use B in A’s finalizer, or vice versa. Finalizers are called in a random order (short of a weak ordering guarantee for critical finalization).
Also, be aware that objects stored in static variables will get collected at certain points during an application domain unload or while exiting the process. Accessing a static variable that refers to a finalizable object (or calling a static method that might use values stored in static variables) might not be safe if Environment.HasShutdownStarted returns true.
See more info on https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
The Netherlands
robert@xsharp.eu
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Gargage Collector and VO->X#-Conversion
Robert,
thank you for answering. I posted this not directly as a question but as a current point of view expecting probable replies because it may be a task also for other programmers.
There is something else what I did not mention directly:
For some of our destructors I see only one possibility that is not recommended by Microsoft: To insert thread locks using the criticalsection functions or the dotnet BEGIN LOCK/END LOCK.
Let's wait and see, I think next week I know if it works, because I have already the test environment that I can let crash the program after about 5 minutes of automated software testing...
thank you for answering. I posted this not directly as a question but as a current point of view expecting probable replies because it may be a task also for other programmers.
There is something else what I did not mention directly:
For some of our destructors I see only one possibility that is not recommended by Microsoft: To insert thread locks using the criticalsection functions or the dotnet BEGIN LOCK/END LOCK.
Let's wait and see, I think next week I know if it works, because I have already the test environment that I can let crash the program after about 5 minutes of automated software testing...
-
- Posts: 178
- Joined: Sat Dec 05, 2015 10:44 am
- Location: Germany
Gargage Collector and VO->X#-Conversion
Arne,
what I have learned is: do not use destructor! Release/close for example files as soon as possible. Use TRY/CATCH/FINALLY to be sure you close files in the FINALLY block.
Resources, that were left over when an object will be killed, are left over because of program failurs. Catch these and act accordingly.
For my dBase app I have a list of open dbf's. In the top level TRY/CATCH/FINALLY I close the remaining.
There ara many ways to avoid destructor.
Frank
what I have learned is: do not use destructor! Release/close for example files as soon as possible. Use TRY/CATCH/FINALLY to be sure you close files in the FINALLY block.
Resources, that were left over when an object will be killed, are left over because of program failurs. Catch these and act accordingly.
For my dBase app I have a list of open dbf's. In the top level TRY/CATCH/FINALLY I close the remaining.
There ara many ways to avoid destructor.
Frank
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Gargage Collector and VO->X#-Conversion
Hi Frank,
you are right. We build most of our code that all critical objects should be destroyed manually. But having 1000 places of code, there will be almost one where it will be forgotten... And it is not easy to find these places: If I register all these objects globally then they are not destroyed. And I have found worse cases: Objects that are destroyed by the GC and that close other objects registered globally in other places. Interesting in how many different places Multithreading can interrupt other code...
Arne
you are right. We build most of our code that all critical objects should be destroyed manually. But having 1000 places of code, there will be almost one where it will be forgotten... And it is not easy to find these places: If I register all these objects globally then they are not destroyed. And I have found worse cases: Objects that are destroyed by the GC and that close other objects registered globally in other places. Interesting in how many different places Multithreading can interrupt other code...
Arne
-
- Posts: 178
- Joined: Sat Dec 05, 2015 10:44 am
- Location: Germany
Gargage Collector and VO->X#-Conversion
ok, multithreading is not mine. I never tried.
Frank
Frank
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Gargage Collector and VO->X#-Conversion
Yes, that is what you can discover with these complex destructors:
Multihreading is automatically in the Dotnet execution - the Garbage collector runs in another thread, probably even on another processor at the same time that the main program does something else.
Multihreading is automatically in the Dotnet execution - the Garbage collector runs in another thread, probably even on another processor at the same time that the main program does something else.
-
- Posts: 178
- Joined: Sat Dec 05, 2015 10:44 am
- Location: Germany
Gargage Collector and VO->X#-Conversion
But in general: the GC only tries to destroy only objects that are not referenced somewhere. So, as long as you have a reference to them, you have the chance to do things right. So clean them just before you set the variable holding them to NULL. Do something like
DocFile:Close()
DocFile := NULL
As long as you have well designed small classes with well defined life cycle you should not have (much) issues.
As I remember right there are huge source about multithreading in MSDN.
Frank
DocFile:Close()
DocFile := NULL
As long as you have well designed small classes with well defined life cycle you should not have (much) issues.
As I remember right there are huge source about multithreading in MSDN.
Frank
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Gargage Collector and VO->X#-Conversion
Yeah ! well designed small classes, where I know what they are doing, I like them also. (Hope that one day we will get rid of the old classes with hundreds of methods with thousands of lines of code calling other untyped classes where noone wants to make many changes anymore)
-
- Posts: 178
- Joined: Sat Dec 05, 2015 10:44 am
- Location: Germany
Gargage Collector and VO->X#-Conversion
What's about a refactoring session in cologne on one of these classes?