Slashdot Mirror


C# Memory Leak Torpedoed Princeton's DARPA Chances

nil0lab writes "In a case of 20/20 hindsight, Princeton DARPA Grand Challenge team member Bryan Cattle reflects on how their code failed to forget obstacles it had passed. It was written in Microsoft's C#, which isn't supposed to let you have memory leaks. 'We kept noticing that the computer would begin to bog down after extended periods of driving. This problem was pernicious because it only showed up after 40 minutes to an hour of driving around and collecting obstacles. The computer performance would just gradually slow down until the car just simply stopped responding, usually with the gas pedal down, and would just drive off into the bush until we pulled the plug. We looked through the code on paper, literally line by line, and just couldn't for the life of us imagine what the problem was.'"

19 of 560 comments (clear)

  1. Well, there's your problem! by feepness · · Score: 5, Funny

    We looked through the code on paper, literally line by line, and just couldn't for the life of us imagine what the problem was. This may be the least effective method of debugging in existence.
    1. Re:Well, there's your problem! by maxwell+demon · · Score: 5, Funny

      No no, that would be something along the lines of printing out the code and then throwing darts at the listing to figure out the incorrect line. I hear it is popular in Redmond, although they reputedly use chairs instead of darts. That makes sense: Since chairs are larger than darts, you have a much greater chance to hit the bugs.
      --
      The Tao of math: The numbers you can count are not the real numbers.
    2. Re:Well, there's your problem! by __aasmho4525 · · Score: 5, Informative

      just to be clear, THE BUG WAS NOT IN THE RUNTIME, not by any stretch.

      there are very clear constructs in place in the language/runtime to allow any object to unregister itself from event registrations it initiated.

      this was VERY MUCH a bug in the end-user software, not the runtime (i've written code almost IDENTICALLY to this and blew lots of time having made this same mistake).

      the only thing the runtime could do to protect the idiot developer (myself included) is automagically make all event references WEAK references, but that has plenty of undesirable side-effects too... in clr, you can do this yourself if you're so inclined... (just like in a JVM)

      cheers.

      Peter

    3. Re:Well, there's your problem! by FreeGamer · · Score: 5, Informative

      It obviously doesn't work in situations like this where the bug is in the runtime and not the application. RTFA. FTFA:

      Though we thought we had cleared all references to old entries in the list, because the objects were still registered as subscribers to an event, they were never getting deleted. We added one line of code to remove the event subscription and, over the next three days, we successfully ran the car for 300 miles through the Mojave desert. As another poster points out, this is just an advert for a profiler, which helps people who use coding practises that they did not initially fully understand. As much as I wanted it to be a bug in the C# runtime, it's just another PEBKAC issue. The /. article introduction was wonderfully ambiguous on this point, if anything it was inflammatory ("C# memory leak"). Poor article selection if you ask me, but it's been many years since the /. editors genuinely cared about the content on this site rather than the number of hits/adclicks.
  2. Slashvertisement by shartte · · Score: 5, Informative

    The linked "article" is just a "sponsored review" for a C# profiler...

    1. Re:Slashvertisement by JanusFury · · Score: 5, Interesting

      The sad thing is that Microsoft offers a perfectly servicable profiler for free that can be used on any C# application and is better than most commercial native Win32 profilers...

      --
      using namespace slashdot;
      troll::post();
    2. Re:Slashvertisement by jmccay · · Score: 5, Insightful
      I think this is just poor code debugging skills. The new garbage collected languages (C# and Java) seem to be creating coders that don't know the basics of debugging. If this was C++, the bug would have shown up when an event occurred and the code called a deleted object. It would have been harder to track down. In any case, I would have added code to analyze the state of the stack and it's objects since it only occurred after the program/car had been running for a while. Also, had it not occurred to them to increase the number of obstacles beyond the "controlled" environment? You can easily write test code to to add a lot of objects into the stack without the use of the car.

      Our cars used an asynchronous event-based code stack written from scratch by us. They wrote their code stack from scratch. They should have modified an existing one that was proven to work. Either way, I think this is a case of sloppy programming. I don't think it is worth mention aside from the case what the closest thing to a memory leak is that you can have. Unfortunately, that too should have come to mind from them. They ruled that out because "most of [their] code is written in garbage-collected C#". Just because a language is garbage collected, it doesn't mean you can just ignore the issues. All reference to the object must be removed for it to be deleted. This is definitely a case of sloppy programming. I would be embarrassed if my name were attached to this.

            Some old Visual Basic programmer jokes come to mind when I read this article. People use to make fun of Visual Basic programmers because it was to easy to write programs in VB. They thought it would produce sloppy code with errors, and other similar things. To some extent, it appears that same case could be made for C#, and to a lesser extent Java. In the end this is simply a case of not stress testing their event stack.
      --
      At the next eco-hypocrisy-meeting, count the private jets used to get to the meeting. Should be interesting to see that
  3. Stupid Slashdot headline by RzUpAnmsCwrds · · Score: 5, Interesting

    This is a stupid, stupid article headline. Of course you can have a memory leak in a managed language! Any Java programmer who's decent understands that.

    It's not C#'s fault. The team had references to the obstacle list (event handlers), which prevented garbage collection. The .NET CLR did its job, just like it was supposed to.

    1. Re:Stupid Slashdot headline by blowdart · · Score: 5, Insightful

      I think you're getting hung up on the method name. There is no standard "delete" function that marks something as unused (dispose on the other hand sort of gets there). The article itself is unclear but I would assume that they were simply deleting the collision objects from a collection of potential hazards. Whilst that would remove the object from the collection itself it is *not* a delete. As references to the object existed elsewhere the object still exists (look ma, no null pointer exceptions) no delete happens. You cannot specifically say to the GC "We're done with this, delete it", the GC sweeps on a regular basis looking for objects with no references.

      Would you really want the GC deciding that just because an object is no longer part of a collection it's safe to unsubscribe it from events and delete it? I know I wouldn't.

    2. Re:Stupid Slashdot headline by slashdot.org · · Score: 5, Insightful

      Of course you can have a memory leak in a managed language! Any Java programmer who's decent understands that.

      Decent programmers might understand that, but let's be honest, it's not like Java (and other GC languages) haven't been presented as if memory leaks were a thing of the past.

      As a matter of fact, some people will probably still claim that it's technically not a memory leak, but instead an object life-span issue.

      What surprises me is that outspoken proponents of managed languages use the garbage collection so often as a good thing, as if now you can be a sloppier programmer and get away with it.

      In reality you have to identify/control the lifespan of objects anyway, so I personally never understood what the big deal is about freeing memory manually. Not to mention that memory leaks in say, C++ code, really aren't that hard to find. The tools have become pretty freakin decent.

      And also not to mention that garbage collection might be handy for memory, but memory is only one of a plethora of resources that can be leaked. And since for many resources it isn't nearly as appropriate to 'lazy' free them, as a programmer you still have to be aware of the allocate/free paradigm. (as just one silly example, it would suck if you wouldn't be able to explicitly close a file, because you can't delete it before it's closed)

      In other words, you are right. Of course you can have memory leaks in garbage collected languages. And I wish people would stop using GC as an argument why languages as Java are so much better to use than C++.

  4. This is not a C# memory leak! by Tim+C · · Score: 5, Informative

    This is a programming error, plain and simple. From TFA:

    Though we thought we had cleared all references to old entries in the list, because the objects were still registered as subscribers to an event, they were never getting deleted.

    So references were held to the objects in two places - the list of encountered obstacles, and the list of event subscribers. They were being removed from the list of encountered obstacles, but not being unsubscribed from the event.

    How do you think event subscription works? Something has to hold a reference to the objects that are subscribed to the event! That thing is going to hold a reference until you unsubscribe the object - it neither knows nor cares about any other list of references you may be maintaining separately, how could it?

    This is a coding error. A subtle, non-obvious one perhaps, but a bug nevertheless. It is not an error in the CLR, and in fact the article never paints it as such. That particular bit of spin is wholly down to the submitter.

  5. Re:I'll show you mine if you.. by El+Lobo · · Score: 5, Insightful
    The problem was not the garbage collector if you read TFA. The articule is just a shameless plug, some ad spam for some very obscure profile.

    This just tells us once again that our wonderful editors on /. don't even try to understand what's behind an article, but they just find some sensationalistic title (the more AntiMS, the better) and done. This results in more comments of the type... "See, M$ id teh SuCkS", or "thanks god for my Linuzzz."..., so they got more profit for their /. ads (oh, the irony often MS ads, BTW).

    Yellow press..... yes, I know, /. is not supposed to have any credibility like any other parasite news sites, but anyway....

    --
    It's time to realise that Abble's products are the biggest abomination these days. Just say NO to the dumb iAbble way!!
  6. don't these kids learn anything anymore? by m2943 · · Score: 5, Interesting

    (1) You are supposed to test your software.

    (2) You are particularly supposed to test your software if you send $200k and 1 ton of hardware careening through the street on autonomous real-time control.

    (3) Garbage collectors do not prevent memory leaks.

    (4) Garbage collected systems can be good for building real-time systems, but you need a real-time garbage collector or you need to treat the system as if it didn't have a garbage collector at all.

    What "ruined their chances" was not that they overlooked a memory leak, what ruined their chances was that they didn't know what they were doing.

  7. Re:Hard/weak references for event handlers by tgd · · Score: 5, Interesting

    Weak references also incur the overhead of a check on every call to ensure the object hasn't been cleaned up. This was sloppy, poorly tested code. The engineers on it made a mistake and caught it too late. It happens.

    The poster of the article was trolling, and not only trolled with the post, managed to get a troll posted to a slashvertisement which was not even trolling.

    Impressive on the part of the person who submitted it, but disappointing considering Taco's comments a few weeks back about articles that are truly nothing but advertisements.

  8. Re:I'll show you mine if you.. by Anonymous Coward · · Score: 5, Informative

    It's not the garbage collector's fault. If an object is still in use, it can't be collected and destroyed. Managed memory only prevents the kind of memory leak where the programmer "loses" all references to the memory and thus never frees it. It also prevents the kind of bug where memory which is still in use is freed. Programs usually crash when that happens (either the OS terminates them due to a memory protection violation or they overwrite their own data and crash later on). That is also what would likely have happened in this case if it weren't for managed memory, because obviously the programmers mistakenly thought that these objects were no longer in use, so they would have freed them when they were still handling events.

  9. Re:Reference counting by Etrigoth · · Score: 5, Informative

    Actually, C# doesn't reference count at all, it 'Reference Traces' :)

    Please, let me explain; it's quite sad how often people don't get this ...
    .Net has its block of managed memory, called the Managed heap. It's separated into 3 'generations'. This heap has 2 areas, free space and reserved space, from top to bottom.

    When you allocate and object to the heap, by using the new command (object o = new object();) there is a set of rules? that have to be enforced:

    • Allocation occures in a contigious range of the freespace, that's as big as the size the clr determines the type to be.
    • The order of objects must be in the order of creation
    • There must be no gaps between objects
    • The oldest objects are in the lowest address space

    The GC manages Reference tracing, and this doesn't occur when the object goes out of scope, it actually happens when the Heap is full and you attempt to allocate a new object.

    In something called 'the sweep', the GC goes through each object in the heap to see if it's reachable. To do this it starts with so-called 'roots'. It then traces to see which objects are referenced by these roots.

    A root identifys a storage location, which referes to objects on the managed heap, or objects that are set to null. For example, all of an applications global and static objects are considered to be it's roots. (hence the reason that all C# apps have a static void main).

    When the sweep starts, it assumes that all objects are garbage. So for each root object, it builds up a graph of the objects that root references, and marks them as being live.
    However, if it finds an object that's already in the graph, it stops traversing that path. This is two (massively) increase performance by not scanning the same object twice, and more importantly, it stops you getting into an infinite loop by scanning a circular list.

    The pinch is, it prevent the circumstance that you mentioned!
    Because the strong reference to a linked circular list is gone, the circular list isn't attached to a root object, so it gets disposed. If you don't want it to get dropped, unless it theres a memory shortage, the C# GC also supports something called Weak References, but I'm not going to go into those here as it's headhurting :)

    So once all the roots have been checked and we've got a nice graph of all the objects that are referenced by the live parts of the application somehow, the second stage of GC happens.

    Any objects that haven't been touched by the walk are of course still marked as Garbage. The GC now walks up the heap linearly, looking for contigious groups of garbage which are now considered to be free space. The GC looks for the next live object and moves it to the start of this free space with a good old memcpy :) This ofcourse invalidates all the root pointers, so the GC then updates the points in the root objects.

    So now, we've got rid of all the garbage and our heap is pleasantly compacted; Take that Heap Fragmentation, Kerpow!!
    But, that's not all she wrote of course :)

    Now we're free'd and compacted, the 'nextObjPtr' is moved to the top of the heap. At this point the new object creation that triggered the collection is performed and the new object appears at the top of the heap.

    This is a dramatic over-simplification and I've not attempted to explain finalization or weak references, but it's still good to know this stuff, it helps us as .Net programmers to consider how to write our code properly :)
    The other thing I've not explained is how the Generations work:

    • We create a new object and the CLR realises that Gen0 is full and a sweep occurs.
    • Firstly, before the sweep and trash, Gen0 has the youngest objects that the GC has never seen.
    • Now that the sweep has finished, all the compacted obje
    --
    When we remember we are all mad, the mysteries disappear and life stands explained.
  10. Re:I'll show you mine if you.. by fitten · · Score: 5, Informative

    There's also the issue where you need to explicitly remove your event listeners when you no longer need the object. The listener keeps a reference to the object (via the interface) so even if it goes out of scope or what-have-you, YOU may think you don't have any references to the object but it implicitly does, through the listener you handed to the system. So... if you're using event listeners, make sure you explicitly remove them in your object's destructure... or else you'll end up with a memory 'leak'.

  11. Re:I'll show you mine if you.. by larry+bagina · · Score: 5, Funny

    Next you'll be telling me that I'm not a nerd and this stuff doesn't matter!!!

    --
    Do you even lift?

    These aren't the 'roids you're looking for.

  12. Re:I'll show you mine if you.. by WED+Fan · · Score: 5, Insightful

    Slashdot is a blog not a news source. I wish more people would realize that.

    ...

    News for Nerds. Stuff that matters.

    O.K., I'll bite, what part of that line do you not understand? If /. billed itself as a "blog" then I'd understand your point. However, /. is a corporate based, self-billed "News" site. Whether reader submission driven or not, it is a news site. You are wrong. But, thanks for your thoughts.

    --
    Politics is the art of looking for trouble, finding it everywhere, diagnosing it incorrectly and applying the wrong fix.