Suggestions for future CDPs?


In my next blog entry, I’ll explain the 11th and final Customer Debug Probe (CDP) that exists in the v1.1 product.  But for the next version of the product (code-named Whidbey), we’re looking at adding additional probes, and not just in the area of Interop.  The goal is to help you find, prevent, and/or diagnose bugs in your managed code by allowing you to opt-in to extra run-time checks done by the CLR.  These extra checks slow down the applications that are probed, which is why you should never have these probes enabled in a production environment (unless you’re debugging).


Take yesterday’s BinarySearch example.  Although many folks figured out the problem quickly, I would categorize that method as error-prone.  Of course, its behavior was consciously chosen for performance reasons.  Why should it force a sort of the array since the careful developer who read the documentation ensured that it is already sorted appropriately?  You’re supposed to pass an appropriate comparer (as Ken suggested) or call Array.Sort first (as Chris suggested) or just guarantee that the array is always sorted in increasing order as elements are added.  But since failing to follow the rules doesn’t slap you on the wrist – it simply gives a wrong answer some of the time – this seems like a potential candidate for a new CDP.


Imagine a “Binary Search on Improperly Sorted Collection” probe that raises a red flag whenever someone calls Array.BinarySearch or ArrayList.BinarySearch on an unsorted (or improperly sorted) array or ArrayList.  Wouldn’t it be nice to have this extra bit of assurance that you aren’t going to ship your software with such a bug?  As long as whomever responsible for QA sufficiently exercises the software with the probes turned on, you would get instant notification of the problem.


But certainly there are more compelling probes that could be added.  Any suggestions?  What subtle issues have you run into when writing managed code?  What hypothetical probes would have saved you hours or days of debugging time?  Of course, I can’t promise that anything would make it into a future version of the CLR, but your feedback is valuable.  We want to make software development enjoyable and less prone to bugs, even if you don’t read the documentation!

Comments (15)

  1. Kevin Westhead says:

    One thing that I would find useful would be to know if a disposable object has been disposed via its finaliser rather than explicitly in code. This normally only happens as a result of an oversight in the code, i.e. Dispose is never called or the code isn’t robust to exception conditions, and it’s something that often goes unnoticed. C# lessons the burden somewhat with the using statement, but its common to see VB code (even on MSDN) as follows:

    Dim d As New DisposableObject()
    d.DoSomething()
    d.DoSomethingElse()
    d.Dispose()

    It should be:

    Dim d As New DisposableObject()

    Try
    d.DoSomething()
    d.DoSomethingElse()
    Finally

    If Not d Is Nothing Then d.Dispose()

    End Try

  2. Ian Griffiths says:

    How about a "Windows Forms Control used from wrong thread" probe? This one catches people out all the time.

  3. Adam Nathan says:

    Those are both very interesting suggestions. Unfortunately for the second one, it’s likely that the probes will continue to be restricted to "core CLR" things, i.e. code in mscorwks.dll or mscorlib.dll. But if nothing else, perhaps a separate diagnostic could be added for such a thing. I believe the Windows Forms folks are already looking into that.

    Any other suggestions out there?

  4. Kevin Westhead says:

    I have another Dispose related suggestion, although I’m not really sure if it lends itself to a CDP. Something that previously caught me out is when "ownership" of disposable objects is transferred. For example, say you are populating an image list with colours, i.e. you generate 32×32 images for certain colours that you want to display and add them to an image list. Personally I’ve gotten into the habbit of thinking along the lines of "If I created it then it’s my job to dispose of it.". Therefore when I create a new Bitmap I know that I must dispose of it, but when I get hold of the Graphics that comes with a PaintEventArgs I know that I shouldn’t dispose of it. I’m not sure if this is the best way to think about disposable objects and this thinking certainly breaks down when adding disposable objects to collections, such as in the image list example above. As a result I ran into problems when attempting to draw the images in the image list since I’d already disposed of them, but the exception messages were sufficiently cryptic ("Invalid handle", etc.) to point me in the wrong direction. You also have to consider that the real bug was in how I was adding the images, not how I was drawing them and my erroneous dispose call was occurring much earlier. A CDP that warned me with something like "IDisposable added to IList/ICollection" would have immediately reminded me that I should think about who’s responsibility it was to dispose of images in the image list. Arguably this can be addressed with better documentation (or better developers <g>) as it’s something that might fire all too frequently, but it was a "subtle issue" that cost me a few hours debugging.

  5. David Levin says:

    Make stores occur as late as possible and reads occur as early as possible and invert the order of them as much as possible according to the rules given for the clr:
    http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/480d3a6d-1aa8-4694-96db-c69f01d7ff2b

    My suggestion above may not be the best way to surface these bugs, but it seems like somehting could be done along those lines…. Any help making multithreaded bugs happen more often seems like a great benefit.

  6. Matt says:

    I CDP to fix this exception would be nice:
    Unhandled Exception: System.DllNotFoundException: Exception from HRESULT: 0x8013
    1524.
    Generated when running code in a created domain. The code works fine in the default domain, but break for some unknown reason in a domain created via
    AppDomain newDomain = AppDomain.CreateDomain("New"+FriendlyName)

  7. Flash Addict says:

    Integrate Flash support into CDPs.

  8. Coupons says:

    One thing that I would find useful would be to know if a disposable object has been disposed via its finaliser rather than explicitly in code.

  9. Read Print says:

    Free books for students, teachers, and the classic enthusiast.

  10. Ryan says:

    Along the same lines… this little bit of code is in the item databound method for a datagrid. I want it to add the text that is in cell 5 of each row in the grid to the arrayList – but only if the cell text doesn’t currently exist in said arrayList. It is not working and is driving me crazy. I’m not sure I am sorting it correctly, but I have read that BinarySearch is supposed to sort it before it does its search. No errors, just always get -1 for ‘location’ even if the same string exists in the arrayList. Anyway, anyone see anything wrong? I appreciate it. thanks, Ryan

    ArrayList ary = new ArrayList();

    ary.Sort();

    string test = eventArgs.Item.Cells[5].Text;

    int location = ary.BinarySearch(test);

    if (location < 0)

    ary.Add(test);

  11. Ryan says:

    ah, well, wasnt the right place to post that question. Anyway, if I can help someone else… I never got BinarySearch to work. I used ‘Contains’ instead and it works beautifully. Here is the code:

    ArrayList ary = new ArrayList();

    string test = eventArgs.Item.Cells[5].Text;

    if (!ary.Contains(test))

    ary.Add(test);