I tested a lot. But I found no disadvantages of those 2!
But see the accepted answer.
I read
here that calling
GetLastError
in managed code is unsafe because the Framework might internally "overwrite" the last error. I have never had any noticeable problems with
GetLastError
and it seems for me that the .NET Framework is smart enough not to overwrite it. Therefore I have a few questions on that topic:
- in
[DllImport("kernel32.dll", SetLastError = true)]
does the SetLastError
attribute make the Framework store the error code for the use of Marshal.GetLastWin32Error()
?
- is there an example where plain
GetLastError
fails to give the correct result ?
- do I really HAVE to use
Marshal.GetLastWin32Error()
?
- is this "problem" Framework version related ?
public class ForceFailure
{
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
public static void Main()
{
if (SetVolumeLabel("XYZ:", "My Imaginary Drive "))
System.Console.WriteLine("It worked???");
else
{
// the first last error check is fine here:
System.Console.WriteLine(GetLastError());
System.Console.WriteLine(Marshal.GetLastWin32Error());
}
}
}
Producing errors:
if (SetVolumeLabel("XYZ:", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming but ok GetlLastError is overwritten:
Console.WriteLine(Marshal.GetLastWin32Error());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(GetLastError());
}
if (SetVolumeLabel("XYZ:", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming and Marshal.GetLastWin32Error() is overwritten as well:
Console.WriteLine(GetLastError());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(Marshal.GetLastWin32Error());
}
// turn off concurrent GC
GC.Collect(); // doesn't effect any of the candidates
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(Marshal.GetLastWin32Error());
Console.WriteLine(Marshal.GetLastWin32Error());
// when you exchange them -> same behaviour just turned around
I don't see any difference! Both behave the same except Marshal.GetLastWin32Error
stores results from App->CLR->WinApi calls as well and GetLastError
stores only results from App->WinApi calls.
Garbage Collection seems not to call any WinApi functions overwriting the last error code
- GetLastError is thread-safe. SetLastError stores an error code for each thread calling it.
- since when would GC run in my threads ?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…