|
Hi Guffa,
here is, I think, the verdict on our GC disagreement:
BTW: I was unable to see disassembly, CTRL/ALT/D is not available in C# Express Edition
(it is in C# Pro, and in all C++ tho). See "How to: Use the Disassembly Window"
on MSDN.
Any suggestion (except the obvious) is welcome.
I studied your program in detail;
in debug, it keeps all the arrays (but not on purpose, as you implied; but rather
because the MSIL did not get optimized, as we will see later)
in release, it throws away everything immediately
The big difference between the two is apparent in the MSIL:
debug generates a call to Create(), then an stloc to save the pointer in a local
(there are 4 numbered ones, the rest is on stack);
in my theory the GC sees these pointers till the method Main() is done.
release generates same call, then a pop, since the arrays are never used,
there is no need to keep the pointers; hence the GC in my theory never sees the arrays.
So I came up with a slightly different test program.
It has two test cases, one very similar to yours,
one more realistic in that the arrays are really used within the method,
so they get stored.
I used smaller arrays but included explicit GC calls, and one explicit ptr=null statement.
Results:
- debug test case 1 keeps everything alive
- release test case 1 does not store a single pointer, so everything is gone
- test case 2 behaves identical in debug and release, it acts according to my
theory: objects get collected if they have no references on stack, either because
the stack unwinds (end of method), or they get nulled.
So I maintain GC does not look at code, it scans the stacks.
And nulling a reference is useful if:
- the ref is somehow global;
- or the ref is local but followed by more code (hence no stack unwinding imminent)
class Program {
static List<WeakReference> refs;
static void Main(string[] args) {
Console.WriteLine("===========================================");
withoutConsumers();
Console.WriteLine("===========================================");
withConsumers();
Console.WriteLine("===========================================");
Console.WriteLine("Hit ENTER to terminate");
Console.ReadLine();
}
static void withoutConsumers() {
Console.WriteLine("Arrays are created but never really used");
refs = new List<WeakReference>();
byte[] ref1, ref2, ref3;
ref1 = Create_1MB();
ref2 = Create_1MB();
ref3 = Create_1MB();
Show("after creates");
Collect();
Show("after collect");
ref2=null;
Show("after cref2=null");
Collect();
Show("after collect");
}
static void withConsumers() {
Console.WriteLine("This time arrays are really used");
refs = new List<WeakReference>();
byte[] ref1, ref2, ref3;
ref1 = Create_1MB();
ref2 = Create_1MB();
ref3 = Create_1MB();
Show("after creates");
int n=ref1[1]+ref2[2]+ref3[3];
Console.WriteLine("n="+n);
Collect();
Show("after collect");
ref2=null;
Show("after cref2=null");
Collect();
Show("after collect");
}
static byte[] Create_1MB() {
byte[] r = new byte[1024*1024];
for(int i=0; i<100; i++) r[i]=(byte)i;
refs.Add(new WeakReference(r));
return r;
}
static void Show(string title) {
string s=title.PadRight(20);
foreach(WeakReference r in refs) s+=" "+r.IsAlive;
Console.WriteLine(s);
}
static void Collect() {
GC.Collect();
GC.Collect();
GC.Collect();
}
}
This is the output it generates in debug mode:
Arrays are created but never really used
after creates True True True
after collect True True True
after cref2=null True True True
after collect True False True
===========================================
This time arrays are really used
after creates True True True
n=6
after collect True True True
after cref2=null True True True
after collect True False True
This is the output it generates in release mode:
Arrays are created but never really used
after creates False False True
after collect False False False
after cref2=null False False False
after collect False False False
===========================================
This time arrays are really used
after creates True True True
n=6
after collect True True True
after cref2=null True True True
after collect True False True
Hope this convincingly illustrates my theory.
[Added: my interest in this got triggered by the idea that ptr=null; without
further consumers for ptr should and would be optimized away by a good compiler;
turns out that MSIL has a ldc.i4.0 to load a 4-byte integer zero, and
a ldnull instruction to push a null reference.
So from this the JIT knows it could eliminate a "ldc.i4.0 stloc" sequence
if the target of the stloc is not alive (life analysis by JIT, not by GC),
but more importantly it will have a built-in rule preventing it from
eliminating the sequence "ldnull stloc". So my mystery is solved.]
-- modified at 20:55 Saturday 4th August, 2007
|
|
|
|
|
Hi Guffa,
here is a code snippet that should convince you a GC can not possibly predict
the future, i.e. it can not predict whether an object that is still reachable
(according to my definition) will still be used, no matter how hard it
investigates the code:
public static void GCCantPredictCodeExecution() {
object doYouStillNeedMe = new object();
Thread.Sleep(1000);
Console.WriteLine("Type 1 to show the object, 0 to skip that");
string s=Console.ReadLine();
if (s=="1") Console.WriteLine(doYouStillNeedMe.ToString());
#if withNullify
doYouStillNeedMe=null;
#endif
Thread.Sleep(1000);
}
So, assuming GC runs at least once a second (if necessary, add GC.Collect()
statements!), when will object doYouStillNeedMe become collectable ?
My answer is:
- D if withNullify is defined since now the ref is no longer on stack
- E if withNullify is undefined, since that's when the stack unwinds to the caller
And if I understood you correctly, you would say A or C depending on what will
be input ???
|
|
|
|
|
Of course the GC doesn't predict the future. It's a bit silly of you to even suggest that I said something like that.
The GC only examines the code, not the data, so any input from the user is irrelevant for the analysis.
The object will always be collectable at point C (unless run in debug mode). Writing a new value to the reference variable does not read the value in the variable, so the GC knows already at point C that the object reference will not be used anymore. When you write the null value to the reference variable, the reference to the object is already unused.
---
single minded; short sighted; long gone;
|
|
|
|
|
|
Even though you may be using only managed code, many of the base classes in .NET use the Win32 API and other unmanaged code internally. The Dispose method is used by the GC to know how to clean up that unmanaged memory.
As far as using (calling) Dispose , it can be safely assumed to be a best practice that if the class implements Dispose (or the IDisposable interface, then you should call the Dispose method when you are done using the class. This is most easily accomplished by the using statement, which defines a scope, outside of which an object or objects will be disposed.
using (Font font1 = new Font("Arial", 10.0f)) If you are writing your own classes, you want to implement IDisposable if
1. you have unmanaged resources that you are working with internally
2. any class in your inheritance chain implements IDisposable
3. you want to explicitly manage the lifetime of the class
You can check out the following references for more information:
Implementing IDisposable and the Dispose Pattern Properly[^]
Using Garbage Collection in .NET[^]
|
|
|
|
|
Thank you. it was really worth reading. Thank you very much
|
|
|
|
|
You're welcome. Glad it helped.
|
|
|
|
|
Hello,
i cant'n connect to my sql server
its' error is:
!qlexception was unhandled
Login failed for user 'sa'. Reason: Not associated with a trusted SQL Server connection.
my code is this:
SqlConnection objConnection = new SqlConnection(
"server=localhost;database=pubs;"+"user id=sa;password=");
that error happened here:
objConnection.Open();
can you help me?
Thank you very much.
H.Jafari
|
|
|
|
|
This question would probably be better in the SQL forum
But in answer to your question:
when you installed Sql Server and it asked about authentication did you leave it as Windows Authentication or change it to Mixed Mode?
If it's set to Windows Authentication then you can't use sql logins.
|
|
|
|
|
No You have a error in Connection String pls modify ur Connection String like that:
SqlConnection objConnection = new SqlConnection(
"server=localhost;database=pubs;uid=sa;password=if any");
Regards,
Karthick
Iam Karthick from Chennai Dot Net Developer
|
|
|
|
|
"User ID" is a valid property to have in the connection string, and the concatonation shouldn't cause any issue either.
http://www.connectionstrings.com/[^]
Which part did you think was incorrect?
-- modified at 9:34 Monday 30th July, 2007
Opps that didn't sound quite how I ment it. What I ment to say was:
Is there something wrong that I missed?
|
|
|
|
|
Hi!
I working on a Pocket PC Device application and i need help
How to verify if another instance of my program is already running? And if another instance is already running I want to make the one already open to get focus.
Please hep me!
Thank you
--------------------------------
visit: http://pmartike.deviantart.com/
|
|
|
|
|
Hello,
Look at System.Diagnostics.Process!
There you will find "GetProcessByName".
Look also at this answere I gave some time ago:
MainWindowHandle[^]
All the best,
Martin
|
|
|
|
|
I am writing following code for impersonation but it doens work.
Can anybody tell me why?
serverConn = new ServerConnection();
serverConn.LoginSecure = true;
serverConn.ConnectAsUser = true;
serverConn.ConnectAsUserName = userName + "@" + userDomain;
serverConn.ConnectAsUserPassword = userPassword;
This connection is used tofr creating database.
Please help
Nana
|
|
|
|
|
hi
Sir,
I have created a Sample Application where a fonts file is referenced from
C:\WINDOWS\Fonts
my requirment is in that my Sample Application should not
use from C:\WINDOWS\Fonts\*.tff path
it use the fonts file *.tff from SampleApplication.resx file
so that my SampleApplication can get fonts irrespective of
font installation in C:\WINDOWS\Fonts
thank u
Fly Like An Eagle With MIGHTY POWER.
|
|
|
|
|
I would appreciate if someone here can help me with the following:
I need to write a small program in C# that does the following:
1. Collect from a user 2 numbers (different bases - Bin, Oct, Dec or Hex) and store them in integer
2. Then collect the operator from the user (+, -, *, /)
3. Then collect in what base the result will be presented (Bin, Oct, Dec or Hex)
4. And then print the result
No graphics is required here. Something to run from the command line.
I know it is simple but could not figure how to do it,
I would appreciate your help here,
Thanks,
Dana.
|
|
|
|
|
So where are you stuck exactly? We won't write the entire code for you.
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
How do I take the 2 numbers from different bases, do the addition for example and present it in a different base?
|
|
|
|
|
guyav99 wrote: How do I take the 2 numbers
Console.ReadLine
guyav99 wrote: from different bases
Depends on how you represent them. You can use string parsing methods or int.Parse()
guyav99 wrote: do the addition for example
Convert them to the same base and use +
guyav99 wrote: and present it in a different base?
number.ToString() with a format specifiert should do the trick
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Parse the strings into numbers using the selected base, do the addition, and convert the numbers into strings useing the selected base.
The Convert.ToInt32 and Convert.ToString methods have overloads that handle different bases.
---
single minded; short sighted; long gone;
|
|
|
|
|
OK, lets assume I collected 101 in base 2 into num1 and 75 in base 8 into num2
How do I write the code for the conversion, adding the two numbers and put the result in a base from the user (say $base_result)
|
|
|
|
|
I have told you how to do it and what methods to use for it. Can't you at least make an attempt at writing some code yourself, before asking?
---
single minded; short sighted; long gone;
|
|
|
|
|
Thanks for the info, however I'm not sure how to do it.
I looked at MSDN and tried to learn from there but still couldn't understand how to do it.
I wouldn't come to the forum if I knew
|
|
|
|
|
Homework?
Standards are great! Everybody should have one!
|
|
|
|
|
Not at all.
I'm trying to build a calculator that can do multiple stuff and this is one of them.
As you can see, I don't ask anyone to program it for me. This is only a small portion of it.
|
|
|
|