Monday, December 03, 2007

Where Did My Object Go? Part 2

In Part 1 of this article I discussed the possibility of an object instance being collected before a method returns in this scenario:

    new MyObject().LongRunningMethod();

as well as this scenario:

    MyObject o = new MyObject();
o.LongRunningMethod();

Here we'll discuss how this could become a problem. Frankly, it's pretty easy to cause the problem, but I think it generally involves some ugliness on the part of software design or implementation, largely involving clean-up of fields when the instance is finalized.


Don't Try This at Home


I don't think it's likely you'll see a lot of code that does this, but here's one way to run afoul of your object going way: export a reference to a field that the object cleans up when it's finalized. You can export the reference, say, by making that field visible through a property. Exposing a field that you're going to clean up in the finalizer would be an easy way to create a coupling between your object and other (arbitrary) client code that has no knowledge of your object's life span.


Call Stack Antics


Another way to invoke the potential problem is to lose your "this" reference on the call stack. The code below manages to lose the "this" reference by passing a field to the helper method rather than allowing the helper to access the field directly via its own "this" reference. When the helper tries to access fs.Length an ObjectDisposedException is thrown.


Why does this throw? Well, the last live reference to the instance was lost when LongRunningMethod passed _input to Helper. Essentially we've again exported the field value from the instance and no longer hold a reference to the instance, allowing the GC to finalize it. Helper is left holding a reference to an object that has been finalized.


Note: Again, you will not see this behavior in a debug build. When running code marked as "debug" the JITter extends the lifetime of the local object to the end of the method. So you will not see this effect if you've compiled with the /debug flag.

    using System;
using System.IO;

// Ugliness ensues.
sealed class MyUglyObject
{
public MyUglyObject(string inputPath)
{
// Real production code would likely not delete the file when done...
// ...but this is a sample app.
_input = new FileStream(Path.GetTempFileName(), FileMode.Open, FileAccess.Read, FileShare.Read);
}

~MyUglyObject()
{
if (_input != null)
{
_input.Close();
_input = null;
}
}

public void LongRunningMethod()
{
Helper(_input); // Our last reference to 'this' (implicit).
}

private void Helper(FileStream fs)
{
// A long-running method can easily experience a garbage collection
// before returning. This one happens for force it to occur.
GC.Collect();
GC.WaitForPendingFinalizers();

// Ka-boom!
long inputSize = fs.Length;
// ...
}

private FileStream _input;
}

class Program
{
static void Main(string[] args)
{
new MyUglyObject(@"..\..\readme.txt").LongRunningMethod();
}
}

Can You See It?


As you can see above it takes a bit of effort to cause the code to blow up. If Helper had used _input.Length instead of taking a parameter the problem would not exist.


But, what I find a bit creepy about the above code is that if Helper were a static method it would seem respectable:

    private static void Helper(FileStream fs)
{
// A long-running method can easily experience a garbage collection
// before returning. This one happens for force it to occur.
GC.Collect();
GC.WaitForPendingFinalizers();

// Ka-boom!
long inputSize = fs.Length;
// ...
}

At first glance it now looks like helper is a normal static helper function, as is likely seen in code bases across the world. It doesn't need a "this" reference, it takes a reference to the object it uses, everything appears fine on the surface. Would you see the "this" reference being lost by the code calling Helper in a code review? I'm not so sure I would have until recently.


 


 


Technorati tags: , , , ,

Where Did My Object Go? Part 1

I ran across this scenario a few months ago and was just reminded of it. It takes a bit of an edge case to make it a problem, but it's interesting all the same.

There's a regular idiom in C# in which we call a method on an object instance that we've created inline:

    new MyObject().LongRunningMethod();

There assumption may be an assumption that the lifetime of this instance of MyObject extends at least until LongRunningMethod returns, but this isn't necessarily true. This same assumption is often made about local references to objects:

    MyObject o = new MyObject();
o.LongRunningMethod();

However, in both these cases the object instance may be collected before LongRunningMethod returns.


Does this really happen?


Yes, it can and does. The code below exercises this behavior. When you run it you will see the following output, indicating that the object was collected and finalized before LongRunningMethod returns:


    Using release build
    Inline
    Entering MyObject1.LongRunningMethod().
    Finalizing in ~MyObject1().
    Returning from MyObject1.LongRunningMethod().

    Local reference
    Entering MyObject1.LongRunningMethod().
    Finalizing in ~MyObject1().
    Returning from MyObject1.LongRunningMethod().

Note: You will not see this behavior in a debug build. When running code marked as "debug" the JITter extends the lifetime of the local object to the end of the method. So you will not see this effect if you've compiled with the /debug flag.


Note also that this article also assumes we're using CLR 2.0. Future versions could obviously behavior differently.


Here's the code. Just drop it into test.cs, run csc test.cs, and execute test.exe.

    using System;

sealed class MyObject
{
~MyObject()
{
Console.WriteLine("Finalizing in ~MyObject1().");
}

public void LongRunningMethod()
{
Console.WriteLine("Entering MyObject1.LongRunningMethod().");

// A long-running method can easily experience a garbage collection
// before returning. This one happens for force it to occur.
GC.Collect();
GC.WaitForPendingFinalizers();

Console.WriteLine("Returning from MyObject1.LongRunningMethod().");
}
}

class Program
{
static void Main(string[] args)
{
#if DEBUG
string build = "debug";
#else
string build = "release";
#endif
Console.WriteLine("Using {0} build", build);

// Try it both ways.

Console.WriteLine("Inline");
new MyObject().LongRunningMethod();

Console.WriteLine();
Console.WriteLine("Local reference");
MyObject o = new MyObject();
o.LongRunningMethod();
}
}

Is this a problem?


Generally, I'd say it's not a problem. Once it has begun execution, LongRunningMethod doesn't need the original object reference unless it's making reference to that instance. In that case the GC won't be able to collect the object.


I'll discuss how to make it a problem in Part 2 of this article.


 


Technorati tags: , , ,

Wednesday, November 28, 2007

File. Close. No!

I enjoyed listening to Scott Hanselman's podcast interview of Larry Osterman today. Larry has been working at Microsoft for more than 23 years now and usually has words of interest to software developers on his blog.

As the discussion turned to security issues I was reminded of a security issue I pointed out to a colleague back in, well, I believe it was the first half of the 90's. The issue: the attack vector brought about by speaker-independent voice recognition. The scenario: the disgruntled office worker running through the cubicle farm, shouting "File. Close. No! File. Close. No!"

It amuses me to think that perhaps the new ribbon-and-pearl command structure of Office 2007 apps has gone a long way in negating that issue. :)

 

Technorati tags:

Friday, June 22, 2007

Whither Orcas?

I've been perusing An Overview of Microsoft Visual Studio Code Name "Orcas" White Paper with a curiosity known only to those who are curious about what will ship in the Visual Studio "Orcas" release. :) I am intrigued. In the three areas in which Orcas purports to deliver key advances, I'm most intrigued with the third:

  • Improve Developer Productivity
  • Manage the Application Life Cycle
  • Employ the Latest Technologies

After all, true geeks are more interested in the latest technologies than in process, right? :) Of interest to me in the Orcas release of Visual Studio, I see:

LINQ (pp. 8,13)

I admit I'm a bit of a Luddite when it comes to language features. It took me a while to see that C#'s "using" syntax was clearly a good thing. What do you expect from a C++ developer whose first C++ compiler was a cfront translator--we didn't have C++ compilers back then. Don't give me syntactic sugar--let me do it the hard way! Give me a preprocessor!

All the same, LINQ seems to be a boon to anyone who wants to query over structured data. I'll likely adopt it in (personal) record time.

Further support for building WPF applications (pp. 5, 19)

Debugging support for WPF. I have to wonder what that will look like. Will I be able to step through XAML?

New APIs in Window Vista (p. 6)

Seriously, are there really "more than 8,000 new native APIs available in Windows Vista?" My brain hurts. Maybe I need to buy a llama farm and learn to live the simple life. I mean, I started programming Windows code in 1991. That's later than many, earlier than most. Dear God, I even digested Kraig Brockschmidt's book, Inside OLE2! Gah! Is my brain going to fill up and return E_OUTOFMEMORY? And will that be a fatal error?! :)

New managed add-in model (pp. 14, 16)

I've seen some tough questions asked about how to control the impact of rogue add-ins in a managed application. The CLR Add-In Team Blog indicates someone at Microsoft is working at addressing these issues, as does this white paper.

Lightweight reader/writer lock with deadlock-free upgrade support (p. 14)

Hmm, a slimmed-down read-writer lock that doesn't support recursion. This sounds a bit like what Jeffrey Richter describes in CLR via C# (second edition, pages 642-643). I can't wait to compare Richter's version in Wintellect's Power Threading library with what Reflector tells me about Orcas' System.Threading.ReaderWriterLockSlim. It should be an educational experience. :)

New IO types that expose almost all pipe functionality provided by Windows (p. 15)

It's about time. :)

A trace listener for ETW (p. 16)

Woot! High-perf event tracing!

Peer Networking Classes (p. 17)

I don't know how much of the P2P APIs this might encompass, but it's definitely an area I'll be experimenting with. I expect we'll be seeing some very cool apps born out of this space. Apps we haven't thought of yet.

 

Woof. As usual my eyes are bigger than my stomach. I hope to have time to explore at least a few of these areas. :)

Technorati tags: , , , ,

Moving On...

It's that time again, when one contract ends and another begins. I'm never able to wrap up all the loose ends that I'd like to.

Yet it's a bit renewing, helping one project through RTM and SP1, then picking up and beginning fresh on something totally different with a completely different set of people. It's interesting how from one project to the next people vary so much. It's like they're wired differently. :)

Aside from the pleasure of meeting and working with new people, I also enjoyed this view from my desk in recent months. (Sorry about the cell phone picture quality.) Can you find the Space Needle?

The view from my desk

If experience is any indication my desk at my next assignment will likely face a beige wall in building 41 instead of downtown Seattle. But it involves some pretty cool software. Oh, well, you take the good with the bad. :)

Technorati tags: ,

Thursday, February 15, 2007

C#: Type issues with ref parameters

I've witnessed a few instances where programmers have tripped up on types when using C#'s ref parameters. Here's a post illustrating this. The temptation is to think that because one can assign a derived type to a base type reference that the same should work with C#'s ref and out parameters.

It doesn't. It's simply not type safe.

The Problem

Here are the types from the above-mentioned post; I've added the FavoriteColor property for later discussion:

    public class Contact

    {

    }

 

    public class Recipient : Contact

    {

        public string FavoriteColor { get { return "Alice Blue"; } }

    }

For discussion's sake, here's the declaration of the method in question:

    bool FetchContact(ref Contact contact, uint row);

FetchContact's signature indicates that it can return a Contact via the contact parameter.

And now the code the poster wants to use:

    Recipient recipient = new Recipient();

    FetchContact(ref (Contact)recipient, row);

It certainly appears that the calling code desires to get a Recipient from the call to FetchContact, but that's not within the interface contract of FetchContact. FetchContact returns a Contact via its contact ref parameter.

Try, Try Again

Now, it's true that the following fragment of code works; it adheres to the interface contract specified by FetchContact:

    Recipient recipient = new Recipient();

    Contact contact = recipient;

    Fetcher.FetchContact(ref contact, row);

Well, of course that works, we've modified the code to pass a ref Contact as specified by the method signature. But why doesn't the first?

Type Safety

Let's try a different tack. To simplify, ignore for the moment that we're looking at a ref parameter. Instead, consider it an out parameter. And we'll also assume that there are more types derived from Contact, for example:

    public class Sender : Contact

    {

    }

Now, consider again, what type FetchContact is returning here as an out parameter?

    Contact contact = recipient;

    Fetcher.FetchContact(out contact, row);

The correct answer is "We're not sure." FetchContact could return a Contact, a Recipient, a Sender, or any other type derived from Contact. The problem of the original code is that it assumes that FetchContact is returning a Recipient and tries to coerce the type. This would not be typesafe as we don't know that the object returned is actually a Recipient.

Consider what happens when FetchContact is (legally) implemented like this:

    bool FetchContact(out Contact contact, uint row)

    {

        contact = new Sender();

        return true;

    }

The object passed back to the caller is obviously a Sender, not a Recipient. The only way for the caller to treat the returned value as a Recipient is to break type safety, and C# generally does not let one do this.

Hypothetically Speaking...

What if C# did let us ignore type safety? Let's suppose that this code could compile and execute:

    Recipient recipient = new Recipient();

    Fetcher.FetchContact(out (Contact)recipient, row);

 

    string fave = recipient.FavoriteColor;

Now FetchContact has returned a Sender that we've coerced into a Recipient reference. Not good. It might execute right up until we use the FavoriteColor property. Think about it. FetchContact returns an instance of Sender, which we're treating as a Recipient. But the Sender type doesn't have a FavoriteColor property. What would happen then? It would surely crash or return invalid data, just as we would see in C++.

C# prefers type safety and doesn't allow this to happen. That's a good thing.

But it's a ref, Not an out Parameter

I believe this is the cause of the confusion around this issue. ref parameters are both in and out parameters. Noone would mind if we passed a Recipient instead of a Contact as an in parameter so why can't we do it here? Because ref parameters, like out parameters, have a stricter requirement: you cannot assume the returned type is a more derived type than the parameter's given type. To do so would not be type safe. The parameter in question must be a ref Contact.

But This Works in Other Languages

This may sometimes work in languages that allow you to subvert type safety (most famously C and C++). It will only work so long as you are lucky about your class layouts or your assumptions remain true. When either class layouts or your assumptions change your code will no longer work.

Here's an example in C++. I run it in the debugger and it crashes on line 20 due to the type coercion done on line 41. This should not come as a surprise.

    1 #include <string>

    2 using std::string;

    3 

    4 class Contact

    5 {

    6 public:

    7     virtual ~Contact() { }

    8 };

    9 

   10 class Recipient : public Contact

   11 {

   12 public:

   13     Recipient()

   14         : m_favoriteColor("Alice Blue")

   15     {

   16     }

   17 

   18     string GetFavoriteColor() const

   19     {

   20         return m_favoriteColor;

   21     }

   22 

   23 private:

   24     int m_otherStuff[256];

   25     string m_favoriteColor;

   26 };

   27 

   28 class Sender : public Contact

   29 {

   30 };

   31 

   32 void FetchContact(unsigned row, Contact** ppContact)

   33 {

   34     *ppContact = new Sender();

   35 }

   36 

   37 int _tmain(int argc, _TCHAR* argv[])

   38 {

   39     Recipient* pRecipient;

   40 

   41     FetchContact(0, (Contact**)&pRecipient);

   42 

   43     string fave = pRecipient->GetFavoriteColor();

   44 

   45     delete pRecipient;

   46 

   47     return 0;

   48 }

 Hope that helps.

Thursday, February 01, 2007

Say (code) what you mean

A bright, shiny object caught my eye few weeks ago while I was hiking in the snowy Cascades. Upon investigation I found a saucer shaped craft glistening in the sun. It appeared to be a space travel-capable sort of vehicle with a translucent bubble-shaped canopy that had sprung open, apparently on impact with this planet. I peered into the craft and saw a gray-green being with a large head and eyes. This being appeared to be well-frozen and so, concluding that continuing my investigation would not disturb this being, I continued to poke around the strange craft a bit more.

In what I would describe as a cockpit I found a something like a display panel which was flashing this message:

Exception in thread "nav" java.lang.ClassCastException: java.lang.Double
at NavigationWaypoint.<init>(NavigationWaypoint.java:10)
at FindWaypoint.FindNextWaypoint(FindWaypoint.java:94)
...

Obviously this sparked my curiosity! In looking around the cockpit I discovered a bit of paper--more like mylar, really--clutched in what for now I'll call the unfortunate being's hand. I liberated this piece of paper and found printing on it. I was shocked to see what the paper showed:

    7 class NavigationWaypoint

    8 {

    9     public NavigationWaypoint(Object name) {

   10         this.name = (String)name;

   11     }

   12 

   13     public String getName() {

   14         return name;

   15     }

   16 

   ...

   32     private String name;

   33 }

What a tragedy! Clearly the author of this code (presumably an inexperienced alien programmer) had errantly designed the instance constructor to take an Object rather than a String. In doing so the coder then needed a typecast in order to coerce the Object to a String in order to set the name field.

I don't know about most, but on my planet such use of a typecast is a pretty strong clue that the programmer should look around to see why the typecast is necessary; it may be indicative of a design error.

In fact, in this case it is a design error. The NavigationWaypoint class has a name field that contains a string, yet the constructor allows the caller to pass in an object of any type. This unfortunate error and the use of a typecast caused the error to manifest itself during execution of the code; obviously some other code passed in a Double rather than a String, probably a simple coding error. If the constructor had been coded to accept a String this coding error would have been caught at compile time rather than during execution, saving this little fellow the exasperation of debugging on the fly and waking up frozen on a strange planet. If only the constructor had been coded to correctly represent the type's data....

 

(This post was inspired by a true story that had nothing to do with navigation.)

 

Technorati tags: , , ,