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.'"
I'll show you my perpetual motion machines if you show me your perfect autonomous garbage collector. You go first.
"There are more things in heaven and earth, Horatio, than are dreamt of in your philosophy."
The linked "article" is just a "sponsored review" for a C# profiler...
There is your problem. Quit using systems that yield blue screams of death (literally).
I prefer the "u" in honour as it seems to be missing these days.
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.
.NET CLR did its job, just like it was supposed to.
It's not C#'s fault. The team had references to the obstacle list (event handlers), which prevented garbage collection. The
collection
I wonder if the Java garbage collector does this also?
FAQs are evil.
Just because a language is garbage collected doesn't mean you can't "leak" memory (in the more standard definition of "waste memory over time"), it only means you can't completely lose track of references to objects (which is often used as a more technical definition of "leak"). It is quite common for people coding in such languages to accidentally generate live object structures that are mostly made up of garbage that they should have released their references to. Put another way: these people's program was legitimately claiming memory and never releasing it due to their limited understanding of how event handlers work.
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.
It's official. Most of you are morons.
AND there's no need for this "trial" version bullshit.
What a bunch of noobs.
I've RTFA, is wasn't a memory leak caused by C#, is was caused by bad programming. After that,the whole article starts to advertise some obscure profiling tool. Maybe they should should have written the whole thing in C++ and use valgrind instead. Just an ideea...
It's not as if C doesn't leak memory when you mishandle resources. All these people needed to do was spend 5 minutes with the (free) MS .NET profiler and look at the allocation and GC graphs, and they'd be done.
using namespace slashdot;
troll::post();
For attempting to use Windows to drive a car. What? are they fucking crazy?
This section totals 15 points.
Background:
There are more types of resource leaks than just memory leaks. A memory leak is when your program keeps hold of memory it's not using. An object leak is when your program keeps hold of objects it's not using. A file descriptor leak is when your program fails to reuse the descriptors for files it has closed and will not reopen. Many other types of leaks could be considered.
Exercises:
1. Determine which issue this scenario describes.
2. Figure out which issue can be handled by automatic memory management.
3. Discuss whether, and if so why, the answers to Exercises 1 and 2 mean there is some conceptual discord between the wording of the scenario and the use of the term "memory leak".
Wow. This is just totally incompetent. I know you're students and all and have no real world experience, but this is just frightening. Stay away from the hardware please, you'll get someone killed one day.
How we know is more important than what we know.
So you think you're better than a garbage collector at preventing memory leaks? Well, maybe you are, but the chance that that is the case (and the chance that that would actually matter) is exceedingly close to 0%. Why stop at memory management? Why not write everything in assembly? Or machine language? People who avoid using useful tools merely because those tools aren't 100% perfect are almost always arrogant idiots who will get left behind as progress marches on.
hundreds of man hours and a few hundred thousand dollars we have finally put our finger on the problem "It was written in Microsoft's C#"...
I don't see why they just didn't write it in C.
They were using massive cooling systems and having very thorough code reviews, sounds like a perfect reason to use C over C#.
The immediate problem here was evidently a programming error, not a bug in C#, but I do wonder why they are using C# for this. That forces everybody involved to use MS Windows and eliminates the possibility of hacking the system if they need to as well as the source as documentation. If they want a C-level language with garbage collection, why not Java or D or any of several others?
What surprises me most is the small size of their software, only 10 thousands lines of source code (I think that the average car processor already have these for today's cars -ignition & braking systems-). Given a team of a dozen programmers working for a year, I was expecting at least 50KLOC, or maybe 200KLOC (for example, the GCC compiler is 3MLOC, and the linux kernel has comparable size.)
Of course memory leaks can happen with garbage collected languages, but these leaks are a little easier to find....
Maybe they should have coded in a higher level language like Ocaml, Haskell.
And yes, I'm sure most of an autonomous vehicle software is not low-level drivers, but in the planification & perception tasks. On such tasks, higher-level languages definitely make sense.
I also did not understood what kind of libraries these teams are using.
I'm also surprised that it is apparently so easy to get funded to have only 10KLOC inside a car!
I see quite a few comments from C/C++ coders who wonder whether managed memory people know how event handling works. If they knew a little more about managed memory languages, they'd know a reference does not have to be "hard": you can have a reference to an object that does *not* prevent garbage collection.
So I guess the real question here is whether event handlers should be hard-referenced (as they are here), or just soft/weak referenced...
From a developer perspective it's quite natural to think that, as long as his code doesn't hold any reference to an object, it should be garbage collectable. If registerEvent() shall hard-reference handlers, documentation should be *very* explicit about it (and the need to unregister a handler for GC to work on it).
On the other hand, if handlers are not hard-referenced you can no longer register anonymous class event handlers...
I'll do the same and when people ask me what language they should use, I'll answer "Pascal."
Garbage collection invites laziness and mistakes, and is generally a bad thing.
:P
One swallow does not a fellatrix make
:(){
Just like most windows machines it bogs down and starts crashing after about 40 minutes of hard use.
In C#, the problem manifests itself as a memory leak. In C/C++ however, you would have freed the memory even while the listeners were still active. Now you have a reference to previously freed memory. I know what I would prefer. The only advantage is that - maybe - the C/C++ error would show up earlier, but the form of the manifestation might vary.
That's why there are no memory leaks in C/C++ code [/sarcasm]
As user of programs written in GCed languages, in my experience usually they are bad memory hogs. And don't tell me that memory is cheap. People constantly forget that we are not any more in the days of DOS, where there was essentially only one program running at any time.
The Tao of math: The numbers you can count are not the real numbers.
There's one other huge huge glaring problem here. You have a system with real-world dangerous consequences that is dependent upon the continued proper operation of the software. When the software fails, the hardware apparently has no safe failure mode. This is a serious no-no in system design where improper operation of the hardware could create a hazard.
It's easy to solve. The hardware should be designed with a watchdog timer that, if it ever expires without being reset, triggers a failsafe mode such as releasing the throttle and applying the brakes. Each mission-critical thread should be required to regularly notify a watchdog thread that it is still running, and the watchdog thread sends the watchdog reset signal to the hardware if all of the mission-critical threads are still running. If any thread exits inappropriately, enters an infinite loop, or otherwise stops being able to respond at an acceptable rate, the watchdog timer times out, and the vehicle stops.
I realize that there is a manual system for stopping these vehicles if something goes awry, but as several teams found out the hard way, safety is absolutely paramount. Belt-and-suspenders is the way to go.
Why not SNOBOL?
Help stamp out iliturcy.
C# does have the facility to use direct memory pointers. The memory these pointers point to is never garbage collected. They are mostly used when access to unmanaged code's object is required i.e com and dcom.
.net garbage collector doesn't clean everything.
Not saying they were using these, but pointing out that the
Lots of bashing about their design decision to use C#, about C# in general and so on. Their decision to use C# seems perfectly logical. Using a high level language to me seems like the ideal choice when writing complex control code. Perhaps a functional language could be even better.
I would have used a modern high level language (java, c# or a specialized language) for the high level control, and I assume that the lower level code device driver and control was written in, for example, c. Makes perfect sense. The fact that the code is described as containing only 10k lines of code just makes the point even more clear. Use the right tool for the job. Use several tools if you need to.
The crash they experienced was because they didn't pay attention to their references properly. Garbage collection isn't any more magic than manual memory management. If you are sloppy the program will fail. The CLR worked exactly like it is supposed to. Unfortunately the fact that having an event handler on an object means that you are referencing it, is sometimes overlooked. If they had been as sloppy while using c/c++, they would have gotten some other problem instead, but the program would have crashed all the same. All this (slashvertisement!) shows is that doing memory profiling and long test runs is important, regardless of which language you have used.
Well the program would have crashed. And they would have known where the problem was instantly instead of requiring a debugger.
Also, what is the point of having an explicit delete if C# just ignores it? This is asked by a person who has never used C#. If I say to delete something, delete it. The program should halt if I try to use an object that has been deleted, or at least it should halt during the next gc when it discovers something has a pointer to it.
(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.
Edit: Nevermind, I should have read further down the page before I commented. I guess my language biases are showing.
This kind of thing makes me so happy. Sure, it's not really a bug in C#, but this is even better, a perfect demonstration of how GC does next to nothing to prevent this type of bug, and instead fools people into complacency while making the bug much more subtle.
In my opinion there is a proper language level for nearly any task. For kernel programming, drivers, or RT stuff, C. User-level stuff is usually better in C++. Well, I'm a big fan of C++ and more comfortable there so I'll usually extend its range down to some lower-level work and sometimes I'll bang out a quick-and-dirty app or script type thing (lots of user input parsing and other things C++ isn't great at) in it too, even if it could be done better (yes, better as in higher quality) or faster in another language.
Anyway, although I could be making incredibly wrong assumptions about the nature of the problem, I'm pretty sure that C# wasn't the right language for the job. C# very nicely occupies the space between C++ level languages and scripting languages, but for a problem that involves probably no parsing whatsoever (it shouldn't, anyway), needs to be perfectly stable (in my experience GC apps are buggier, I'm not going to go off on that tangent now and explain, but it's been my experience), and have as deterministic runtime as possible, it's C or a subset of C++ (little to no STL) all the way. This paragraph was brought to you by Lisp.
This problem was caused by, I'm going to go out on a limb here and say the wrong language choice. If this was C/C++, there would have been a segfault (easy to debug--usually) or the old reference wouldn't have mattered at all. C#'s real strong point, its huge and well-integrated library, probably didn't help them out very much.
Every programmer who wants to call themselves a real programmer should learn as many languages in as wide a range as possible. Sure, have favorites, but that should mean trying to work in your language's realm, not extending it way beyond its range.
<xml><I><am><so><damn>Web 2.0</damn></so></am></I></xml>
Well the Event Subscribed 'problem' is well known and makes sense if you think about it. I mean subscribing to an Event means placing a pointer to a delegate of a method in a event subscriber list.. when someone raises that event then each delegate in the list is invoked... so basically it is an implicit reference and hence can prevent the it from being marked for garbage collection.
;) :)
However, i had another memory 'leak' problem where the Garbage Collector simply didn't collect in time which caused my application to use more and more memory until it reached the system limit and crashed... i found that simply calling
GC.Collect();
GC.GetTotalMemory(true);// (the true 'forces' collection
once would fix this problem... i though i needed to call it every minute or so... but when calling just once it did SOMETHING that prevented this problem from occurring again.. no idea exactly what.. but it works
Yes but errors always happen.
Justice is the sheep getting arrested while an impartial judge declares the vote void.
Instead of doing lots of news and deletes on the fly, why not allocate enough memory when the program starts and use that instead? That way you won't fragment your memory pool either, or have those age long garbage collection sessions. Anyway, the topic of today is bad programming, move on, nothing to see here.
Spit!
Blatant slashvertisment and also a misleading title trying to blame stupid programmers' mistakes on Microsoft and C#. Spit! Spit! And... spit!
"I'm not much interested in interoperability. I want substitutability. I want to be able to throw your software out."
After being convinced by salesmen telling it will solve all your problems, you spend money on a proprietary development system/language coming from a company well known for anticompetitive practices and tied to a closed platform. Then, when your code bites you in the ass, someone tells you another proprietary software would have solved all problems, and you're forced to waste more money. Sounds familiar?
Of course it does! It's the L. Ron Hubbard way of doing business, applied to the IT field.
No thanks, I'll stick with GCC: it's way more productive than the above stuff, unless one thinks productivity is just a matter of doing the same thing in two lines of code instead of five, regardless of performance, optimization, peer reviewing, being in control of what the software does, etc.
Looks like they can't directly blame C# for not releasing memory while they are still holding references to the supposedly deletable objects. But I have seen appallingly low understanding of OO principles among the candidates I interview who had grown up in C# environment. My big grouse is that even in C++ Visual Studio and .NET IDEs inhibit a big "picture" understanding of large and complex code. The number of times I had to berate newbies for including afx.h in a "platform independent" base class headers ...
sed -e 's/Chuck Norris/Rajnikant/g' joke > fact
The last few large projects I have worked on with C++ had no issues with memory leaks on product release and these were servers that run for months. Proper use of smart pointers and correctly designed classes is not that hard. The last Java based product I worked on had all kinds of leaks and issues.
They can't have had anyone on the team with experience of coding for Swing in Java then - you get these all the time, sometimes hanging tens of megabytes of unwanted GUI objects off a single listener registration, and learn how to spot and fix them.
Yikes. So these guys have the smarts to make a computer drive a car on its own, but managed to forget some basic safety mechanisms such as a watchdog and other failsafe mechanisms ?
Geez guys - real world engineering 101: Do not let a computer control anything that might have a remote chance of harming someone without appropriate safety mechanisms.
They also didn't pick a very good hack because it didn't leave the car in a safe state when the software broke.
Lack of practical experience I'd say. A few more events like that and they'll make decent devs one day.
Every half way decent programming language will allow you to leak memory.
Its trivial to show this as long as the language supports some sort of array. Garbage collection is useful, but it does not save you from memory leaks. I don't know how many times I've told some retard JavaScript "programmer" that yes, they do have to be mindful of memory leaks even though their language has a garbage collector.
Mathematics is made of 50 percent formulas, 50 percent proofs, and 50 percent imagination.
I'm not convinced that the company got any cash out of the coders given it exposed the problem straight away...
From TFA:
"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."
Whatever issues the software guys had, the hardware control guys are the real story. They designed a machine that they KNEW would run out of control with potentially deadly results. If it had run over someone, these guys would surely be arrested for manslaughter. Now imagine they can't "pull the plug" because they dropped the remote control, AA batteries died, got out of range, etc. Now you have a out of control truck heading for that group of Boy Scout hikers, a highway or other contestants.
Who the hell was supervising these students? I want to make sure I don't hire anyone from THAT school.
Place nail here >+
It is a poor carpenter that blames his tools.
A nice quote from Eric Sink's Source Control HOWTO:
Recently when I asked my fifth grade daughter what she had learned in school, she proudly informed me that "everyone in Korea eats kimchi at every meal, every day". In the world of a ten-year-old, things are simpler. Rules don't have exceptions. Generalizations always apply.
This is how we learn. We understand the basic rules first and see the finer points later. First we learn that memory leaks are impossible in the CLR. Later, when our app consumes all available RAM, we learn more.
Ok, so the headline is bogus...
But what a lost opportunity for a Reboot Fix, in the grand tradition of MSware throughout history. Just think, an automatic reboot for your robot car, plane, spaceship... and it just keeps going! (or, more properly, starts going again -- now, where was I?)
Geeky modern art T-shirts
Those new, shiny languages like java and C# are often promoted as something magical that absolve developers entirely of memory management issues.
The truth is that garbage collection are tuned based on heuristics that are not necessarily adapted to the workload of your particular program. But since it's designed and sold as a system to take memory management out of your hands, you can be left clueless as to what the fuck happens, and end up with problems even more complicated and obscure to solve than when you do manual or semi-manual memoetry management and something leaks.
Give me C++ RAII any time along with reference counting smart pointers and I'm happy. Sure, circular references are a problem, but some people (among which Mr. Boehm) are working to include the concept of litter collection in the next C++ standard (basically a garbage collector that could be ran at a very low frequency and only intended to pick up the trash left by the smart pointers, ie circular references)
... disagree. Yes, there was glitch they picked up with the way they dealt with the GC. But when they enter the car next year, using C#, they'll be able to get much further.
Which means that the language did the job very nicely.
Don't you get it? It's not the language, it's the programmer. I vaguely remember people saying that everything should be done in assembly instead of C or C++. Look where that got them. The truth is, any capable language used correctly can almost always do the job you need. C# is no exception.
XML is like violence. If it doesn't solve the problem, use more.
Even worse is the reaction of the developers when they found that after about 40 minutes of driving things became uncontrollable (without safe failure mode, as you point out). They just decide to reboot the system based on a mere timer without understanding what's going on or where the 40 minutes time frame originates. And on top of that they don't seem to mind that their reboot might occur at a critical moment as well, which not only does not address the original "accident waiting to happen", but introduces a second one as well! These people are dangerous and should never be let loose in an engineering environment at all.
Linux user since early January 1992.
I just read TFA and it doesn't give any details. My guess? I just checked, and C# apparently uses reference-count garbage collection. That means that an object will stay around until there are zero references to it. The best way to create an object that will never go away is to create a circular linked list, then delete the reference to the list. All the items refer to each other, but there is nothing else that references them. But any complicated data structure that can have circular references will leak memory.
A mark-sweep garbage collector will catch this, but at the cost of interrupting the program temporarily to do GC. This isn't exactly friendly to real-time applications.
So basically this looks like a classic noob blunder. Just because there is "automatic" garbage collection doesn't mean that you can turn your brain off.
#naabhaprzrag, #sverubfr-000, #agi-fcbafberq, negvpyr[pynff*=' negvpyr-ary-'] { qvfcynl: abar !vzcbegnag; }
Unintentional object retention. I think that is the official name of the problem. It occurs with managed languges. You have a big application with hunderts of objects referencing each other, it's inevidable that you will forget to null out a reference somewhere. (and by the way this is not exclusively a problem of event handlers, it can happen anywhere).
The solution it to use weak references.
When I switched from c++ to java, it seemed very obvious to me that this would happen, I just assumed that all experienced coders were using weak references. Out of curiousity, I asked on the forums how many people use weak references, the answer was "what is a weak reference?". Then I explained it's to prevent weak references, they just laughed at me: "dude, we have a garbage collector, we don't have to worry about memory leaks"
That is why you shouldn't use other companies 'tool kits'. You never know what garbage they have introduced, nor can you do anything about it.
---- Booth was a patriot ----
They've simply neglected to remove the event handlers for the "obstacle" objects, so they were still referenced and wouldn't be garbage collected: "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, maybe it's better to read and understand the article (which does seem like an advertisement to ANTS profiler), before just bashing an innocent programming language with no reason at all...
I love these DARPA challenges, and they seem to be working better for Uncle Sam than handing over gazillions to greedy, incompetent 'cost-plus' military sub-contractors. Good publicity, too...
On the other hand, whilst I know it's 'the American way' to have a unique winner, perhaps the nexy step would be to encourage winning teams to create reusable, modular compotents / subsystems. Every winner is a unique expression of its creating team's creativity and technical competence. DARPA gets to keep the winning team's tech. Great. But will it blend - sorry, scale?
If, each year, the teams could build upon ALL the previous teams developments, (kinda like FOSS model), then surely we'd all move together faster. No need to write lines of code for stereoscopic vision - use the module that worked best last year. Collision avoidance logic required? Download latest stable from Sourceforge, or secure DARPA equivalent.
It's like the X prize - Rutan did a great job with SpaceShipOne, but nobody is pretending that it's really a technological stepping stone to civillian (orbital) space flight...
A funny thing happened with during my co-op this summer:
I was working at a coal-fired power plant which needed a new pollution control device before 2010. There, I would dig through the literature, and try to find suitable products and operating conditions for this device. Anyway, this involved a lot of meetings, conference calls, and business lunches with the suppliers in question.
Then there was Joe.
Joe was our Alstom sales rep: portly, humorless, slow to speak and slower to understand. He was also a devote Utahnian.
Well, one day, we were killing time while waiting on a conference call, my supervisor left the room, and we started talking about universities. Then he dropped the bomb:
"In my Senior year, I worked on developing perpetual motion machines."
My supervisor then reentered the room, and we got back to work. I felt like I'd just seen a dancing frog.
People! Of course it's a memory issue -- not a leak, as everybody else has explained, but of course the issue is that your system got memory-poor. Of course. Nobody every checked the Windows task manager to say "Gosh, no more memory. Maybe that hurts us?" You don't need a profiler to figure out what this problem was; it probably helped to figure out where the problem was.
The bigger question is, who sets a reset timer and considers their problem fixed, and, even if you don't have the timeline to find and fix the problem, who times the reset to the magic number of 40 minutes and not to the degrading performance?
The truly amazing thing is that people bright enough to build the rest of this system could be so remarkably clueless about basic debugging.
Yes, there are leaks, sometimes because people make mistakes, sometimes because a poorly documented API is used, sometimes because a programmer is inexperienced or feeling lazy that day.
That doesn't change the fact that a language is a tool, and using a difficult tool requires discipline, while using a more friendly tool makes for lax behaviour and hides the cause of errors.
I'd rather use a sharp kife than a food processor, for example - it's easy to produce amorphous mush if you're lazy with the food processor, while a good knife chops only what you ask it to.
One swallow does not a fellatrix make
No, but you don't often get C/C++ programmers going "well, it'll not be a memory leak, let's look elsewhere".
Chernobyl 'not a wildlife haven' - BBC News
ANTS doesn't fix Microsoft CLR problems. ANT fixes programmer problems. In other words, the logic was flawed. They didn't release their references properly and therefore the garbage collect didn't collect because the objects were still "in use". Princeton and DARPA and bad programming
Congratulation John Backus, you have just reinvented the first programming language.
Dynamic memory became an official feature of Fortran 90, although it was a common extension much earlier than that.
Older programs, also written in languages other than FORTRAN, tend to prefer static arrays over dynamically allocated arrays. As a result, older software tend to be ridden with fixed limits like max line length or max identifier length. In fact, the prime advantage (besides being free) of the GNU utilities over their Unix predecessors, was that the GNU utilities relied on dynamically allocated memory much more, and as a result got rid of most of the arbitrary limits. This was especially noticeable as the Unix utilities had static limits that made sense for applications running in the 64KiB memory space of the PDP-11.
Garbage collectors may be fine, but for some solutions they can be a problem.
And of course - it's possible to get memory leaks just about everywhere regardless of programming language. It just depends on how "smart" the programmer is.
If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
It was written in Microsoft's C#, which isn't supposed to let you have memory leaks
The CLR would have the memory leak, not C# which is just compiled into IL. Could've been VB.NET, Python, JScript, J#, F# etc. etc.
This is clearly a programming mistake: they should have known they needed to unregister their event handlers.
;-)
But more basically, this is bad design: if you're going to create so many objects you can crash the computer so fast, you should be using a pool of these objects in the first place (and reuse them). Why spend so much time allocating new objects and garbage collecting them?
Finally, this is the wrong environment. If you're going to control a car driving in real time, wouldn't it make sense to use a real-time environment (language+OS) ?
Gee, when i think those guys can find thousands of dollars for such a project and i can't find a job...
Their refined choice of restaurants and overspending may have lead to less funds available for the computer coding.
... you have to keep track of everything you allocate and be sure you clean it all up when you are done with it. That need does not go away with C# or other languages like Java. The danger with C is not that you might forget to free some object, but rather, that you do free some object and forget to remove a reference to it.
now we need to go OSS in diesel cars
when I worked for Bell labys/Avaya, one of our switches was made with windows. We had to put in double the hardware for half the call capablities, and the damn thing crashed so often, that it quickly became the "blue screams of death". That thing sold at just 1.5 times our others switches in that matrix, and it was our only money loser.
I prefer the "u" in honour as it seems to be missing these days.
Just read the CodeProject article to see why:
;-) )junk near them in the game, hence not getting garbage collected due to their object detection algorithm.
- "so it wasn't a memory leak per se"
- "It was the closest thing to a memory leak that you can have in a "managed" language. "
- "Unfortunately, our system was seeing and cataloging every bit of tumbleweed and scrub that it could find along the side of the road."
So they just goofed up.
The objects didn't get deleted in time, because there were always ( literally
Bad Slashdot. Bad Slashdot.
Beware: In C++, your friends can see your privates!
I can't believe more people modded the parent with interesting than informative. Unlike other posts that rants about bugs in C#, it is informative. TFA says:
In essence, they really have two obstacles lists, one of which---the event subscriber list---is a mirror of the one being updated by stereo vision. Whoever wrote the code didn't decide correctly what to do about the mirror.
I once had a signature.
Criticisms of the team aside, I would like to say that neither Java nor C# have made any steps to remedy problems like this with seem to be all too common with inexperienced developers. Both Java and C# need to support attaching to event handles with "weak" handlers. That is, the handler will not hold onto the object which defines the handler (and will automatically deregister itself sometime after the object has been collected). In many cases, there is a need for an object to listen and handle an event from another object, but only whilst the object that is listening is still referenced (with the exception of the reference held by the object firing the event).
In C#, the (admittedly ugly) way to implement this is to use an anonymous method and a weak reference: The "closure" that is created for the anonymous method does not hold a reference to "this" as it does not access any of "this"'s fields or methods unless it's through the weakreference.
The code has a flaw where the event handler code (only a few bytes to hold the closure) will never deregistered be collected unless the event is fired sometime after the owner object has been collected. This can be fixed by using a NotifyingWeakReference (a weak reference that raises an event when it has been collected).
After all, to the average non-Redmondian, "Microsoft code" and "defects" are too often synonymous, no?
As others have already pointed out, this isn't a C# problem. The objects weren't getting freed because there were still event handlers referencing them.
.NET and Java provide them, but you have to make proper use of them.
Note to beginning C# programmers: A good way to avoid these types of problems is to use weak references when wiring up a large numbers of events.
I have a little utility class called WeakEvent which just uses an anonymous delegate to check if the object's still alive. If so, it calls the event. If not, the delegate removes itself from the event chain. Problem solved.
Your only other option is to remember to unsubscribe from every event when you're done with a listener object, so that it will be collected -- which pretty much defeats the purpose of using a managed language. Weak references: both
Do you honestly not realize that EVERY programming language is compiled into ASM? The irony is unbelievable...
If there's $2 million at stake and you're doing real time programming then use a proper programming language and OS.
C/C++/ASM on a real time OS.
Yes it's hard work, but get your algorithms and design right and you should be able to implement it in anything.
Guess MS designed Windows to be like an elephant and never forget anything.
Mod me up/Mod me down: I wont frown as I've no crown
This is simply an example of bad programming.
Objects are eprobably stored in a list of some sort, and no LRU (least recently used) checking is used to purge the list based on time.
This is the kind of poor programming I would expect from J#/java/C# programms who are accustomed to 'let the software do it for me'.
The same can happen in C/C++/Java/Basic/ADA/Perl.....
Thats what you get for getting cut-rate programmers who cut their teeth on the language of the lowest common denominator.
I will bet an embedded programmer would have found this in 10 seconds or less.
This is only a sales pitch that tries to sell a software tool.
I would have tested my software before the competition deadline. A heapdump would have shown their issue. You don't have to buy tools for that. Maybe they should buy a book.
And yes, the same problem would have happened when they used java, or any other software language.
At LAX, the Windows API call gettickcount() had an overflow problem,
requiring a monthly reboot if the application wasn't coded around it.
One time in 2004, the person responsible forgot, and the controllers
at LAX couldn't talk. The problem isn't really Windows, it's a lack of
good software processes.
Here's what didn't happen effectively:
http://it.slashdot.org/article.pl?sid=04/09/21/2120203 (LAX down due to comm system failure)
http://it.slashdot.org/article.pl?sid=07/08/15/1829256 (LAX down due to NIC card failure on PC)
Slashdot editors are even more pathetic than I thought they were. It's bad enough that they didn't skim through the article, but they apparently didn't even take a look at the URL. Look at this thing:
http://www.codeproject.com/showcase/IfOnlyWedUsedANTSProfiler.asp
"IfOnlyWedUsedANTSProfiler"? That didn't raise any flags?
Of course, I'm trying to assume good faith and not just conclude that the editors knew this was an advertisement, but they sure are making that difficult.
From the TFA I assume some kind of callback handler still kept references to the object preventing automatic GC.
This seems straight forward enough however this alone should not have caused the system to fail.
Having the system lock up with the gas pedal depressed in my estimation is a very troubling design flaw that in itself even without the GC bug should have disqualified this group from participating in the grand challenge.
People using high level codes for automated vechicles or automated sentry guns without necessary modeling to assure acceptable failure modes deserve what they get.
Reading the article makes me perplex.
I wonder why the programmers don't use a real time os with a real time language.(this doesn't seem to be the case reading the article)
I agree it may seems harder to program at firstt but a good conception can avoid these stupid case when the car just bump into something because the computer hasn't been able to calculate in time...
Having seen a real car taking 10s to answer to the stop button because it was buggy in certain conditions and the manufacturer had just released the car too early to respond to market pressure makes me afraid of what we will see in the future when car becomes more and more automated...
which is a good thing - a program that crashes during development is easy to fix. A program that slowly gets worse and worse and is only noticed when shipped is difficult to fix. I know which I prefer, from bitter experience! And to top it all, this was a 10k loc program, hardly anything major - imagine you had one of these leaks in a million loc app, built out of a dozen components.
...on slash dot if it was written in perl on the linux platform. This is just an oppurtunity for someone to read part of a story, make a snappy title that bashes Microsoft based on the misunderstanding of the technology in an article.
This is not a c# memory leak, it was a memory leak written in c#. The developers used a commerical tool to find there problem, a trail version even. So how about a title "Commercial Code Profiler Saves the Day For DARPA team"?
Oh because then it would never be a slash dot article, ugh.
Developers making a mistake != c# bug
The IDisposable interface is there for a reason.
How has no one mentioned that they're running the car on windows? I think that was their first mistake...
It wasn't a memory leak caused by the C# garbage collector, it's the fault of the programming team not removing their event listeners properly.
I usually like /. articles, even the ones against MS, but I cannot just skip over this one:
if the moderator read the article he would have noticed that the article was an advertisement for the profiler product, not just a review of it (it was written directly by Red Gate).
Second, the article itself says that they found that the error was in how they coded the application, because they left some reference so the garbage collector didn't trow away the objects.
This is a really bad article and bad information.
Come on. Really. What kind of idiot marketer sends in stories like this to Slashdot? We know what happens. First, you get derided mercilessly for trying to sway us with your ridiculously transparent attempt at marketing. Then, the real experts come out and poke holes in everything you've said. Then everyone else chimes in with better (and often free) alternatives. You and your company end up looking like buffoons, and your product ends up looking like utter garbage.
You may think you're pulling one over on the editors, and maybe you are. But you aren't pulling one over on us, and I think after all these years, the editors know this. So, just don't. Unless your product or service is absolutely bulletproof people here are more likely to shoot it full of holes than rush out and buy it.
- None can love freedom heartily, but good men; the rest love not freedom, but license. -- John Milton
1) As anti-Microsoft as I am, this was not C#'s fault. They had a hidden reference to the objects that were not getting garbage-collected. The way this article is posed, however, is blatantly FUD. Shame!
2) The article itself is a not-so-veiled advertisement for a profiler.
Some other folks at 4 or 5 already have commented on the fact that this is not a C# bug or a .NET bug, but a programmer mistakes, so I will not elaborate.
But the article linked to was authored by "RedGate Software" for the Code Project, so it is basically an advertisement for their product. Their product did help the team fix their bug, so maybe that is good.
But the bug was discovered and fixed in 2005:
http://pave.princeton.edu/main/archives/114
So what happened is that probably Red Gate wanted to score some PR points over at the Code Project and they digged up a story from their existing customers, decided to sponsor the guys in exchange for a few quotes that they could put on the article to promote their product.
It would probably not gone too far, except the guy that submitted the story thought he had found the smoking gun against C#.
Miguel.
Wrong... in at least two ways. Not every programming language is compiled. Usually compiled programming language generates binary code ( aka machine language ) not ASM code.
They designed a machine that they KNEW would run out of control with potentially deadly results. If it had run over someone, these guys would surely be arrested for manslaughter.
They were not designing a production machine for the road. Their machine was a product of research into autonomous vehicles, designed to work in a government laboratory. In this case, the laboratory was the Mojave Desert.
When a robot falls over or overheats and catches fire in a research lab there's no call to jump up and shout about how the creators made a dangerously flawed machine. When a chemist leaves a reaction heating too long and the result is a toxic chemical instead of the intended medicine, there's no reason to get up in arms. It happens all the time in laboratories. The Princeton team forgot to add a reagent to a beaker, and their experiment didn't work. If this kind of thing didn't happen with autonomous vehicles there would be no need for DARPA to mount a competition to design them.
potential_bs_str = "We had vacations coming up a few weeks after the race, so we left the cars in Vegas and returned, two weeks later, to investigate the problem."
if(bs_test(potential_bs_str)){
prints("Nobody takes vacation before problem solved in Real World");
} else {
Remain_skeptical_anyhow();
};
A man spends the first half of his life accumulating stuff, the second trying to get rid of it all.
Why would anyone write a vehicle navigation system in an interpreted language anyway? Microsoft gives out these languages hoping people will use it, yet none of their code actually uses it. C# reminds me of GWBasic from the 80's or Visual Basic from the 90's.
Managed languages should have a a delete statement that acts like an assert. It tells the GC that this object should be deleted now, and the GC looks at the object and throws an exception if there are any references to the object. It doesn't have to actually delete at the point, but it is a way for the programmer to ask the CLR "Are there any other places that reference this object? If so, I want to know about them so I can fix them"
Instead, there are $5,000 tools that try their best to guess what objects are supposed to be deleted, and come up with tons of false positives and things.
On a related note to this, it sounds like their particular problem was with C# events holding objects. There are various people who have made weak-reference events that prevent this problem in the first place. It is rare that you want an object to be held alive just because there is an event on it.
If you are into snuff films you should check this out.
I've always said that if you use Microsucks shitware, you get what you deserve.
I code everything in assembly. It's much easier to debug than C, C++, C#, Java, or damn near any other language you can name. The only drawbacks to assembly is that it's insidiously non-portable, and you need to keep in mind all kinds of issues that a good compiler can deal with for you -- it takes me about 3 times longer to write a complex assembly function than it takes me to write the C analogue. So why code in assembly? What I get in return is completely transparent debugging -- I can step through my code per instruction in a debugger, not have any mysteries about execution order, what the optimizer is doing, etc. The resulting code is typically between 30% and 200% faster than compiled C code. That's a huge win for system library functions or core computational routines that will be used in tight loops. I can't speak for the grandparent, but I don't "avoid using useful tools merely because those tools aren't 100% perfect". I avoid using tools which are the wrong tool for the job. The question I have is: what job is Java/C# the right tool for? I can't think of one. If performance matters, really really matters (I mean, lives and dies by cycle count), then they're too slow. If performance isn't so important, there are more powerful languages in which it's easier to write clean code. These guys at Princeton probably could have written everything in OCaml / Python / Lisp and had no troubles at all. As for getting left behind as progress marches on... I'm a young guy. I'm the only young guy I know who writes production quality assembly. Interestingly, I also get paid more than my other friends who are software engineers, and I have no worries at all about my job being shipped out to Elbonia. I look at the output of bleeding edge compilers, and work with compiler guys to try to improve their backend codegen. I know they told you in school that compilers were smart, and you should just lay out your algorithm properly and trust the compiler. They lied. My job's not going anywhere.
So, if I understand the "article", the rookie students got caught with their pants down on bad coding practices and should have used any of tools, free or not, to profile their app and find the problems before going to production.
Can you imagine the folks at Red Gate trying to convince them:
Lessons learned, but I hope every employer will keep their picture handy, in case they get a resume from anyone on the team.
Politics is the art of looking for trouble, finding it everywhere, diagnosing it incorrectly and applying the wrong fix.
I'm from team Cornell, #26. We finished the race (although slowly due to what looks like a buggy throttle controller). C# was used exclusively in our system for the strategic planner. It was also used quite a bit for the behavior/operational systems.
I'm very much a C++ programmer, and with a strong focus on micros to add to that, so yeah, I was a bit... skeptical.
At one point in development we did have a "memory leak" issue but it was entirely our fault (while obviously there are no "new"/"delete"'s around, if you don't dereference things then essentially you get a nice "memory leak" with all of the associated symptoms).
I think that C# really sped up our development time, and, in the end, our car finished. I'm sure that there are other fully valid languages/IDEs/etc, but we happened to be most proficient in MSVS; we tested the crap out of C#'s compiler's performance on our machine for our specific application; we used it and that part of the system performed admirably. C# also let us write numerous support utilities quickly.
Microsoft may have many faults but I'm pretty sure that C# / the Visual Studio IDE environment as a whole aren't it.
Princeton seemed to have a number of issues outside of "slowing down" during runs. They completely scrapped their first two qualification runs, ran maybe once, and then left.
P.S. No, i'm not paid by microsoft or such. Aside from the usual departmental benefits like free copies of MSVS and winXP, we didn't get any kind of sponsorship from them.
There's actually an accepted safe way to do memory management - reference counts and weak references. That's what both Perl and Python have settled on, and it's worth noting that programmers in those languages seldom have serious memory management problems. In C and C++, one has to obsess on memory management issues, and even in Java and C#, which are garbage collected, it takes more attention than it should.
Reference counts have the advantage of repeatability - deletion will occur at predictable times. This allows the use of destructors. You can safely use destructors to manage other assets, like windows, open files, network connections, and such.
Destructors in systems with garbage collection make for an unhappy marriage. Calling a destructor or finalizer from the garbage collector is essentially equivalent to calling it at some random time from another thread. So race conditions are possible. Check out Microsoft's "managed C++" for an attempt to get all the cases for this right. It's not pretty.
The classic complaint about reference counts is "what about cycles"? There's a simple answer - cycles, that is, loops of strong pointers, are errors. This isn't a severe restriction; it just requires some data structure design. With trees, for example, links towards the leaves are strong pointers, and links towards the root are weak. (I've revised Python's BeautifulSoup HTML parser to work that way; "down" and "forward" links are strong, while "up" and "backwards" links are weak. It took about 20 lines of code and eliminated annoying problems in programs dealing with HTML trees.)
If you really need a symmetrical circular list, which might happen in, say, a window library with many links between widgets, there's a simple solution. Have all the objects owned by some collection, then use weak pointers between them. When the collection is dropped, all the bits and pieces go away, in a well defined order.
In Python, you can turn off garbage collection while leaving reference counting active, then list any orphaned cycles at program end for debugging purposes. This is a practical way to program without leaks or garbage collection. It's generally easy to find cycles, because cycles are created by data structure design, not by bugs. So if a program has cycles, it will probably have them every time, and thus they can be found early in debugging. With better language support for debugging, cycles could be caught at the moment of creation, which would make it easy to eliminate them.
Now if we could get this into a hard-compiled language, we'd have the problem solved. Repeated attempts to bolt reference counting onto C++ via templates have resulted in fragile systems. The fundamental problem is that C++ still requires access to raw pointers to get anything done, and this puts a hole in the protection provided by the reference counting system. It takes language support to make this work right.
People complain that Slashdot sucks: the headlines are sensationalistic, the editors get commissions based on the number of dupes they post, and articles about 6-month-old events get posted as "news".
So why do I even bother visiting Slashdot? The answer is two things: the community of posters, and Slashcode moderation.
The value of Slashdot is in its community. You and I, dear Slashdotters. Our collective mind will pick through the various articles, point out their flaws, expose sensationalist FUD for what it is (and, surprisingly, will do this equally for anti-Linux and anti-MS FUD), debate various trends, and provide a signficantly international (though heavily USA-centric) perspective.
This value is enhanced by Slashdot's moderating system, so that information and insight can bubble to the top among the mass of inane posts. Metamoderation limits the amount of crack that the moderators can be on.
So, Slashdot editors, take note! *WE* are the reason we are here. *YOU* are not. Many of us don't even bother to read the articles any more, preferring to soak up the collective wisdom of techies from varying age groups and fields. If you piss us off, and the collective community of Slashdot deteriorates, then there's no reason for me (or others) to keep coming back.
Think about it.
404555974007725459910684486621289147856453481154 in hex is "You sank my Battleship?"
[GPG key in journal]
Not so much. That's an artifact of the interface. Most compilers will output assembly language, and the tool chain will convert the assembly files into binary machine language afterwards (by calling some form of assembler). You might just as well say that most compilers generate executable images, because most compilers will chain to the linker unless you specify otherwise.
I suspect it is the fault of slashdot user base as much as the editors. I bet a lot of users were in the firehose, saw the sensationalist title, etc, and rated it highly. The editor comes in, sees it has a sensationalist title and is now colored read, meaning users really think it is great, and posts it. So yes, the editor may not have read the article, but I'm sure the user base didn't either, at least not until after it got posted.
Beware of bugs in the above code; I have only proved it correct, not tried it.
When you reference and make calls to unmanaged Win32 DLLs, you can run into leaks real quick. Because those libraries run on Win32 C++ code, it is still up to the developer to reclaim that memory within their .NET managed code.
For example, if you use the GDI+ library, you have to explicitly call the Dispose() method to free up the memory it is using, otherwise your C# app will continue on its merry way with that memory still allocated.
We're all hypocrites. We all have hidden parts, it's the contrast between them that make us more a hypocrite than others
Using a garbage collected language for this is really stupid. To add to the choir, this is not memory leak, so C# is not really at fault here. There's another issue with GC languages, however. Every now and then runtime will suspend all application threads and run garbage collector. Your program is _stopped_ during GC, which means the car doesn't "see" anything through its cameras, doesn't control throttle, brakes or steering wheel. In a desktop or a web app, you won't notice a few milliseconds of interruption. Choice of C# for this particular application, however, strikes me as odd. You need a language where you can control everything and which doesn't get interrupted unpredictably - C, C++, Ada - there are a number of different languages people use for realtime computing.
The only thing I would expect that is left out is a reference to the fact that if the system had been validated by WGA (Windows Genuine Advantage) that the memory leak would not have existed. Every time one of my students pays for Microsoft software, it doesn't work. Only the cracked coppies work!
LMAO!! These morons were probably using "legit" coppies from Microsoft, thus the WGA invalidation, and thus the failure of their vehicle.
Even ONE decent debugging tool would have told them what was going on, but Microsoft sues anyone who tries to publish a real debugger that can show what's really going on in DOT-NET.
I think the license agreement even prohibits benchmarking or reporting on the performance of ANY code written in DOT-NET. If that's the case, then these poor schlubs have violated the EULA by mentioning that the code stopped responding, and their entire university is liable for piracy.
I predict that within 24 hours, Microsoft will:
1. revoke all academic licenses at their school (without telling them)
2. sue everyone who attends their school
3. call the ATF / BSA / SS / FBI HRT tactical teams to go after select team members. Watch for that school to look like Waco, TX did on 4-19-1993.
Andy Out!
that they bombed it and got money from "Ant" for "fixing" it later?
That's weapons development at it's finest. Just ask the Sgt York team.
I'd go on a Vegan diet but the delivery time from Vega is too long. --brownkitty
It's not a memory leak. It's an object life-span issue.
It isn't a memory leak. It's an object life-span issue.
"We had vacations coming up a few weeks after the race, so we left the cars in Vegas and returned, two weeks later, to investigate the problem. One of our team members downloaded the 14-day trial of ANTS Profiler and we ran it on our car's guidance code. We profiled the memory usage and saw the obstacle list blowing up."
Except a C programmer would have done this before even starting up the car.
"ANTS Profiler helped us fix a problem in minutes that would have taken us weeks to track down. If only we'd thought of it before the competition, we would most likely have finished the entire race and had a chance at the top prize money."
Which is why newer fisher price languages with automatic garbage collecting are bad in the long run - they don't expose the programmer to enough manual intervention such that they take it for granted.
Humans are incredibly prone to complacency.
And, of course, very few will actually read the article. This wasn't a 'bug in C#'. Not even close. It's a bug in the programmer. They left a reference hanging around to objects they no longer needed, thus the object never was garbage collected. "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. "
:(){Is that supposed to use up all the available process IDs?
http://outcampaign.org/
Misleading headline. They had a stupid bug in their code that caused the leak. (Easy to make, but stupid nonetheless)
Question: does C#/CLR have weak refs as a feature? Seems like event listeners ought to be registered as weak refs by default to prevent this sort of problem...
...cut 'em some slack.
If these were seasoned pros, then yeah, they would deserve the jeers... but "student" implies "still learning the craft". This is the sort of mistake they are expected to make once in a while.
Don't blame C# for memory leaks. Blame the mediocre software testing that was applied (or not applied) to this project.
Not really, the people that don't clean up object references in memory managed languages are the same people that wouldn't manage resources correctly in a non memory managed language. For good developers the memory management removes a lot of work that really isn't needed. There still needs to be care placed in to ensuring you clean up references though. I would put some blame on folks that teach/market these languages like as if you don't need to worry about memory at all. Of course you need to worry about memory, just in a slightly different and usually less intensive way.
Hey, here's a wacky idea that's just crazy enough to work - DON"T USE DYNAMIC MEMORY ALLOCATION! Why in holy hell would someone construct what amount to an embedded real-time system using dynamic memory. Define fixed memory allocations for everything. Run tests. If the memory is insufficient, the program crashes. Then you can see where the program crashes and why. Then you can fix it.
Just because you *can* do something doesn't mean you should.
Brett
At this point, everyone expects an anti-Microsoft bias from Slashdot, but this crosses the line into blatant misinformation. Pure and simple FUD. The submitter either doesn't understand how memory management works in a managed language or just doesn't care.
Garbage collectors cannot release "unused" memory if they cannot tell the memory is unused. Poor coding skills and an assumption that a magical garbage collector will save you is just not smart. I can easily code something that eats memory like no tomorrow and never releases one bit of it in Java, C#, etc... managed languages only work if you code with them correctly. Blame the developer, not the language.
- I voted for Nintendo and against Bush
If only we used ANTS profiler? Is this really news or a commercial block? Give me a break.
And why did they use C# for this project?
Unfortunately, the supermajority of home PCs do not run a modern operating system. They run Windows.[1] Unlike UNIX file systems, which store inodes separately from file names, Windows stores them together. Unlike a UNIX system, which removes the file from the directory and schedules the inode for deletion once all processes have closed it, Windows does not allow a file to be deleted if any process has it open.
[1] Some people claim that the NT kernel is beautiful and the Windows userland screws it up.
Then why not fuck off somewhere else?
Deleted
In which case why use a high level language at all - surely coding everything in Assembler would be the way to go.
Microsoft's history is full of software engineering flaws and anybody who continues to use their products in a critical tool is playing a fools game. Microsoft's #1 goal is not technical excellence and never has been. And I'm not saying that Microsoft is the only one to do badly at software engineering, it is just that they are so good at doing it repeatedly.
BTW, remember when LAX was shutdown for hours and there were a few in-flight near misses because the LAX Comm system went down? That was because they used Windows 98 to run that COMMs system and it had a flaw which caused it to crash after something like 38 days. IIRC, this flaw was only found something like 3 years after Win98 shipped and goes to show you how unreliable Microsoft operating systems are. Nobody could keep it running for over 38 days for over 3 years. And then, some bozo decided to base a rewrite of a UNIX based air traffic COMM system on Microsoft Windows....
IMO, the Princeton guys were idiots for picking Microsoft "technology" for this project.
LoB
"Anyone who stands out in the middle of a road looks like roadkill to me." --Linus
Slashdot has editors. I know this, because the stuff below "nil0lab writes..." is heavily editted from what I actually submitted! In fact, I started my actual submission with something like "in a shameless plug for some code analysis product..."
I sent this story to slashdot, and I'm not a marketer nor do I have any
relationship with the product. In fact, I started my submission (which
was editted, see other comment above) with something like "in a blatant
plug for some kind of profiling product..."
If a delay of a few milliseconds is a serious concern you really need an OS you can tightly control too.
note: i'm known as plugwash most places but i screwd up registering that here somehow in the past and now can't register
To pronounce C# in the non-musical:
See-hash
"Nine times out of ten, starting a fire is not the best way to solve the problem." - my wife
That is not a C# memory leak: "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."
That was just some bad programming and debugging.
<^>_<(ô ô)>_<^>
Besides that, what good is it to advertise a C# profiler to slashdotters. Slashdotters would never use c# to begin with (since they consider it devil-spawn).
He was also a Utard.
There. I fixed that for you.
I have been developing and running large scale C# applications over 4 years now. I had seen some performance inconsistencies, but never a complete stall. When working with automatic garbage collected framework, it is important to understand that such inconsistencies are part of the equation. If one wrote a hard realtime app on top of the framework, how could it be MSs mistake? I'm convinced that this could only be a programming mistake or a high leve decision making error where they decided to use C# for not what it is good for.
Not only that, but the entire thing ends up being indexed by google, so the next time someone is looking for your service, they end up with a /. discussion by experts mentioning how bad the product is and how good and cheap the alternatives are.
Help! I'm a slashdot refugee.
It's a very dark ride.
More appropriate title would be "Memory leak in program written in C#".
I cannot for any amount of time believe that any of the teams used a Microsoft product and expected it to be perfect. Open source was the way to go on this one and they blew it.
I would never drive a car or fly and airplane that has Microsoft software in it, so what were these guys thinking?
Anyone read the article? They were using stereo vision to detect obstacles. That is pretty cool. However, I have doubts that they wrote this part themselves because nobody with reasonable mind would use C# for image processing. It is possible a DirectShow filter doing the processing, and the C# code uses managed DS. The biggest problem is they have the obstacle objects listening to an event? Why? What kind of event would they be listening to? Anyone care to guess?
Just in case anyone is confused, this is about the Grand Challenge in '05, not the most recent Urban Challenge this year('07).
I was on the Utah DARPA Urban Challenge team, and Princeton was supposed to test right after us every day. Neither of us made it to the finals, and I question the logic that they used in eliminating teams so early. We only had 1 opportunity to try test tracks A and B, and each time we fixed the minor bugs that stopped us. If we had had a second try on either of these tracks, I think we would have had a shot at the finals, but they cut us just as we thought we had all the bugs worked out, and before we could show them what we could do.
I think most teams have stories about what went wrong, and what they should have done, that they didn't do. I know that we did. I know even the winners have goals for what they want to do better next time.
-John Fenley
The developers can't debug worth shit. I've run into similar problems in production code (such as graphics contexts in java or cyclical references) and it usually doesn't take that long to figure it out.
Pretty shoddy debugging... IMO. Too bad CS departments don't put more emphasis on debugging.
Camping on quad since 1996.
First off, the article intro should be updated, unless /. would like to further capitalize on the false (and defamatory) title. There was no "C# Memory Leak" in this code just as there is no "C memory leak" in other similar, poorly-tested programs.
I was sadly unsurprised when I read TF Advertisement and found that, in fact, C# and the runtime had been working perfectly WRT this problem. The delegate reference (anonymous function pointer) was holding a reference to the target object, the source of the event, just as expected.
Second, I am shocked that this bug was not used as a "learning moment" for the people working on this project. This type of problem will continue to vex these people as they move from academia into the real world of building systems and applications. That is, until they learn how to debug problems. A significant portion of a developer's time is tracking down and fixing this sort of thing. It's also something that would have been found rather quickly with basic debugging skills.
For future reference, here's a little tutorial.
1. Start the system and let it run.
2. Watch memory consumption. You may even use a basic tool such as the Task Manager on Windows (although I'm sure, what was it?...Red Gate, is a fine product).
3. If memory consumption grows unabated, you have a leak somewhere. Time to start instrumenting your code.
4. Look at all of your allocations (grep new *.cs), start with those key objects that there are likely to be a lot of (e.g., ones that get added to lists).
5. Add two static variables to any such classes: allocatedCount and deletedCount.
6. Restart the program.
You can trace or dump these variables and start watching trends (liveCount = allocatedCount - deletedCount). If it had been done in this program, the problem would have been spotted instantly. You're lucky that it was a leak--usually easy to find--not the kind of "Heisenbug" that can bite developers in other languages, like C, in which an uninitialized variable can cause a problem to only show up sometimes; for example, only when run for 10 hours and only when run outside of a debugger.
When working on problems like this, the kind that can take hours or days to find and fix, the finding part is what takes all of the time. The diagnosing and fixing part is usually pretty quick and painless. The delegate reference that was the cause of this problem would have been spotted pretty quickly, I would venture.
The result of GetProcesses() won't free up the memory once it leaves scope, nor does manually going in and freeing the individual Process data. I even tried freeing the individual members of the class, elements that should have been marshaled in.
I had a problem using this in a loop, ended up using a different technique to get the information I needed (I was scanning for a process starting up and shutting down). My app consumed over 1GB in an hour, before I figured out the culprit, I tried forcing garbage collection, finally ended up doing a post-mortem on the heap and seeing that bits of the Process information data was still sitting out there, somehow orphaned, then attempted to remedy that, but C# apparently prevented me from freeing those orphaned elements. My "fix" was to use instances of the Process performance counter (all I needed was the names of the currently running processes), and I've tested it over a period of days with no memory consumption (beyond the initial 20MB or so the app needs to run)
The lesson here is: Don't use GetProcesses() in a loop.
Serves them right for using C#. You'd think in today's world everybody would write their code in C or C++ and use algorithms that don't dynamically allocate memory, then use flexelint, then use a memory tester as the final step. No, these half wits use M$. They've got to prove they can't do things right and are so stupid they'd put their fate in M$'s greedy hands. I'd like to see more articles like this one! Little ivy league schoolers getting burned for being incredibly stupid. Didn't Bush and Kerry come from Princeton... No wonder these kids are using C#!
Memory leaks only happen in compiled languages. In managed languages, it is called "packratting".
As many have already said, this wasn't a "C# memory leak", but an app bug, and solutions have already been offered (use weak references, or just remember to deregister event listener at the same time as the app deletes the event listener object from the collection).
But I think people have been missing what the real problem was.
From what I'm reading in TFA, the problem wasn't really a "running out of memory" issue, it was that more and more event listeners were being registered, so every time an event occurred it took more and more time for the event to fire. They say that after 40 minutes or so, the system began to get slower and slower and slower, and would eventually grind to a halt. I think the problem wasn't lack of memory, but that eventually gazillions of event listeners were registered so it took forever to call them all.
-- "I never gave these stories much credence." - HAL 9000
Surely you were asking for it. C# is a propreitary language, written by *one* company. The only reason I can possibly think of for such an inane choice is that Microsoft might be a sponsor.
They also had a hot chick soldering, the iron slipped or something an part of the circuit board exploded ala Star Trek. Good episode.
Let me try to come up with a statistical explanation. More often than not people programming in VB are concentrating on shallow tasks. (e.g. only MS Office applications) Their "good enough" and "I feel lucky" attitude is not counterbalanced by concerns that come with experience of solving tricky tasks in heterogeneous systems. So they can not foresee what is not "good enough" from their limited experience.
I saw people running SQL queries for each value from a list, instead of creating a table and doing all in one table scan. This all worked until the database got more workload and could not come back with results in time anymore, making the application unusable. Did they have to work with mass-data server application, where one learns to always try to be efficient with production code, they would have seen this ugliness and invested a bit more time.
...a stunned silence fell upon the hall.
Ok, then the next question is why did you submit a product plug as a story? And why would the editors accept a story labeled as such?
It is the library, in particular event notification, that "caused" the problem. The language was fine. The same thing happens in Java when beginning programmers forget to unregister objects from event sources (or anything else requiring registration). I use the term "data cancer" to distinguish this type of bug from actual "memory leaks", which are in fact impossible with a working GC.
Why? Because you also are too stupid to dereference your objects so a GC can clean them out?
Automatic GC is a lot like a pair of nunchucks. If you walk down the street with them whirling it around, it looks pretty badass and no doubt you can hurt someone as intended. After your first street thug goes down, you definitely feel like badass. Just don't confuse yourself with Bruce Lee. You'll likely wind up giving yourself a black eye with 1 bad twirl. Deterministic GC is a lot like one of those kung fu fold-fans. Really hard to do damage, but one of those old, bearded guys will tear you a new asshole with it. Kung Fu baby.