Slashdot Mirror


Pros and Cons of Garbage Collection?

ers asks: "Most new programming languages are using garbage collection, rather than programmer-controlled memory management. The advantages are obvious: programmers no longer have to worry about forgetting to delete allocated memory, leading to far fewer memory leaks. The disadvantages are often glossed over by programming language designers - aside from the performance issues, predictable memory management can be used for controlling access to files and similar resources, creating safer thread locking code and even providing better error messages. Some programming languages, which usually predictable memory management, can also be made to behave like they are garbage collected - for example, Boost provides various C++ smart pointer classes. So, given the choice between garbage collection or manual memory management, which would you choose and why? When using a manual memory management language, when do you consider the performance and syntactic overhead of faked garbage collection to be worthwhile?"

56 of 243 comments (clear)

  1. C++ basically has it right by keesh · · Score: 2, Insightful

    The C++ model is basically correct. It doesn't treat the programmer like an idiot (which admittedly may be a problem if you have idiot programmers), and it gives you the choice of how to handle memory allocation. The lack of reference-counted pointer in the standard library is a bit of a bitch, but the Boost shared pointer templates will likely make it into C++0x, and it's only a hundred lines of code or so to make your own in the mean time.

    Of course, the C++ model is not perfect either. Lack of virtual and const constructors can be a nuisance (the workaround being the pimpl idiom and a shared pointer), and not being able to use shared pointers to functions without nasty syntactic hackery occasionally breaks the "stuff pretending to be a pointer" illusion. Still, the power it gives over the Java model is definitely worth the occasional bit of extra effort.

    Then again, if you're coding some quick scripting hack rather than a proper program, who cares about memory allocation?

    1. Re:C++ basically has it right by try_anything · · Score: 3, Insightful

      I don't think garbage collection implies treating the programmer like an idiot. The programmer's attention is a finite resource that is often better spent on something other than memory management, especially given that garbage collection performs quite adequately for many programs. A Perl, Java, or Lisp programmer isn't an idiot for not doing his own memory management any more a person who doesn't make his own shoes is an idiot.

    2. Re:C++ basically has it right by Pseudonym · · Score: 3, Insightful
      The C++ model is basically correct.

      On the contrary, the C++ model is basically correct for some applications.

      A "proper program" is programmed in the appropriate language for the job. Sometimes this is a domain-specific language. Sometimes you need the close-to-the-metal-yet-still-maintainable-for-larg e-applications qualities that C++ provides. And sometimes you don't.

      Very few people write web applications in C++, and for good reason. Web servers run at the speed of the network card, not the speed of the L1 cache. Pulling out extra cycles is pointless especially if you lose the maintainability that a general purpose language like C++ provides. And yet you wouldn't call many of these "quick scripting hacks".

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    3. Re:C++ basically has it right by Oscaro · · Score: 2, Insightful

      I don't think garbage collection implies treating the programmer like an idiot. The programmer's attention is a finite resource that is often better spent on something other than memory management.

      I have mixed feelings regarding garbage collection. Sure enough when people are learning how to write programs, it's far better to use a language garbage collection, so that one has to really understand what's happening. Also, having to manually keep track of your data can lead to cleaner code (I know one can write clean code in Java, too, but given the "lazy" nature of people (or the strict timeframes) this is really not too common).

      On the other hand, your argument is painfully valid. The programmer's attention (and time) is a finite (and scarce) resource.

    4. Re:C++ basically has it right by Westley · · Score: 2, Informative

      In C# structs are allocated on the stack.

      No, they're allocated "inline" with the variable (if there's one involved) or on the stack if they're part of an intermediate expression. The mantra of "struct => stack" is one which has confused many people in my experience. See http://www.pobox.com/~skeet/csharp/memory.html for more details. (I'm only picky about this because of the confusion that this has caused.)

      For limited-lifetime objects, C# actually has a built-in keyword. It's called using and it works along with the IDisposable interface, regardless of whether your object was allocated on the stack or not.

      Calling Dispose doesn't change the lifetime of your object (well, it might suppress finalization). It's to do with releasing resources *other than* the memory taken up by your object itself.

  2. Depends by Apreche · · Score: 4, Insightful

    It depends on what you are trying to make, duh.

    If you are trying to make something where performance is important, like a 3d game, then manage memory yourself. If you are making a simple business application where reliability and security are important, use garbage collection. If your program uses lots of RAM and you need every last drop either find an expert at RAM management to get every last bit or use garbage collection if your programmers are not so awesome.

    And so on and so on...

    --
    The GeekNights podcast is going strong. Listen!
    1. Re:Depends by ivan256 · · Score: 2, Insightful

      Actually, it seems to me that if you want reliability, maintainability, and perhaps most important, debugability, you want to manage your memory yourself.

      When debugging a program with a leak (Yes, garbage collected programs have leaks too, they're just nastier, because they don't look like bugs because a reference is persisting somewhere.) if memory is program managed, finding the leak is a deterministic process. You're guaranteed success in a well-defined, and finite amount of time (The amount of time it takes to reproduce the leak plus the amount of time it takes to build the application, plus the amount of time it takes to get a basic understanding of the application structure). When you're debugging a leak in a memory managed environment, you're limited to the tools provided, which are pretty much universally not good at finding the worst kinds of leaks, because to the tools your leak looks like perfectly valid utilization. You're really doomed if your leak is in a third party library. You may never track it down, or even find the culprit. (Any Jakarta users out there?)

      Sure, languages without garbage collection may be more prone to leaks, but I'd rather have more leaks that I can fix, than fewer leaks that I can't...

      Not that garbage collection doesn't have it's place. If you're application is complex enough though, allocating your own memory is the least of your worries.

      If your program uses lots of RAM and you need every last drop either find an expert at RAM management to get every last bit

      I don't care what kind of programmer you are, you should have a good foundation in certain things. Data structures, obviously. Discrete logic. Algorithmic complexity, including the ability to read and understand Big O notation (wspecially true of java programmers)... And a complete knowledge of basic memory management. Even if you're going to use garbage collection. Without these things, you're doomed to write poor programs. If you don't understand how a utility library works, you shouldn't be using it.

    2. Re:Depends by swillden · · Score: 4, Insightful

      It depends on what you are trying to make, duh.

      Agreed.

      If you are trying to make something where performance is important, like a 3d game, then manage memory yourself.

      It's not that simple.

      In most cases, the total run-time cost of garbage collection is lower than that of malloc/free memory management, at the cost of higher on-average memory usage (which can obviously destroy performance if you end up having to swap). On the other hand, application-tuned manual memory management using pooled allocation is generally faster than GC. Whether or not pooled allocation increases memory usage as much or more than GC depends on many things. Another consideration is that although GC often consumes less total CPU cycles than malloc/free, non-incremental collectors tend to use those cycles in big batches, which can produce GC 'pauses'. That's bad for some applications. Incremental collectors can minimize this effect, but only with some cost in CPU cycles.

      Then there's also the whole issue of the effect of different approaches on the multi-tiered memory caching in modern systems.

      In short: yes it depends on what you're trying to make. No, it's not nearly as simple an analysis as you describe.

      Not only that, in practice other constraints usually dictate the choice anyway. Using GC generally means using something like Java, C#, Python, etc. rather than C or C++, which brings in a whole raft of other considerations, many of them more important than the memory management discussion. Platform, target environment and libraries will often dictate language selection, which will dictate much of memory management approach.

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    3. Re:Depends by toddbu · · Score: 2, Insightful
      not sure how you can call the former unpredictable...

      Because in many systems that employ GC, they try to free resources on background threads for performance. The problem is that a resource can be held way beyond what the developer expects, and suddenly they get faults happening in totally unrelated sections of code. I've seen it a million times before, and I personally think that it's one of the biggest weaknesses of the CLR. When a function is done with a resource, clean it up right then and there. At least then you'll have some chance of figuring out what's going wrong.

      Oh, and for all you folks that say that nothing should ever crash in cleanup, think again. Microsoft will tell you that publically, but there are lots of things that you can do to make an app crash in GC, like manually cleaning up some stuff yourself before exiting the function. The GC routine will get very confused trying to clean up a partially cleaned up object.

      --
      If you don't want crime to pay, let the government run it.
    4. Re:Depends by alienw · · Score: 2, Insightful

      Are you joking? A large fraction of bugs in software are due to mismanaged memory. This is one of the main reasons Java apps have much, much better reliability than C++ ones. Without a garbage collector, many types of (perfectly legitimate) structures become very difficult to use. When you create objects in one module and give them to someone else, you create bugs. Then you have to come up with some kind of reference counting system anyway.

      Yes, garbage collected programs have leaks too, they're just nastier, because they don't look like bugs because a reference is persisting somewhere.

      That's not a leak, it's sloppy programming. Are you saying it is better to leave stray pointers around and potentially crash the program or corrupt data?

    5. Re:Depends by Spy+Hunter · · Score: 3, Insightful
      I fail to see how following a chain of references to a memory hog is harder than finding a memory leak which has nothing pointing to it at all. In a garbage-collected application, with a proper debugger and profiler you should not have any trouble figuring out exactly what's taking up every byte of your memory, and once you've done that you can easily figure out who has the references to it. I recommend you take a look at Microsoft's awesome CLR profiler; I'm sure a similar tool exists for Java but it may not be free.

      It is just as easy to keep references to unneeded objects in C++, so C++ can have the same types of so-called "hard to debug" leaks you blame on garbage collection. But on top of that, if you have a true memory leak, C++ doesn't even tell you what's stored in all that leaked memory. You'll just have to trace back to find the last guy anywhere in the code who threw away a pointer without deleting it, and it could easily be very tough to figure out. And C++ doesn't have a magical solution to leaks in third-party libraries either.

      --
      main(c,r){for(r=32;r;) printf(++c>31?c=!r--,"\n":c<r?" ":~c&r?" `":" #");}
    6. Re:Depends by archeopterix · · Score: 2, Interesting
      Actually, it seems to me that if you want reliability, maintainability, and perhaps most important, debugability, you want to manage your memory yourself.
      And try to pinpoint which of the hundred thousand totally unrelated functions has modified my data because it happens to use a bad pointer?

      I had to debug a C program that started crashing after an unused variable declaration had been removed. The reason? - a dangling pointer.

      The program was compiled without any optimization, so the memory for the variable had still been allocated (in spite of the var being unused), which shifted the other variables to that the dangling pointer had missed them. After deleting the unused var, the pointer (used totally elsewhere) damaged the data.

      Managed memory gets you rid of this kind of problems. Or, at least, confines them to external libs written in non-managed languages.

    7. Re:Depends by Mr.+Slippery · · Score: 2, Interesting
      When you create objects in one module and give them to someone else, you create bugs.

      No, the caller of your module creates a bug when they fail to free the object that you have clearly defined in the interface to be their responsibility. It's no different than any other violation of an interface condition. (If you don't clearly define your interfaces, then yes, you have of course created a bug.)

      That's not a leak, it's sloppy programming.

      Are you saying that leaks are not a form of sloppy programming? You've either failed to free things you knew needed to be freed (your sloppiness) or you've failed to know which things needed to be freed (which could be your sloppiness or someone elses').

      --
      Tom Swiss | the infamous tms | my blog
      You cannot wash away blood with blood
    8. Re:Depends by ivan256 · · Score: 2, Insightful

      so C++ can have the same types of so-called "hard to debug" leaks you blame on garbage collection

      I said they become more difficult to debug because of garbage collection. They're certainly not caused by the garbage collection. They're caused (usually) by poor programming.

      Garbage collection is a tool. It makes your job as a programmer easier, but it does not free you from the need to understand things like scope. Just because you don't have to worry about the mechanics of managing your memory, you still need to understand how it works, or you are going to write crappy code. Code that leaks.

      But on top of that, if you have a true memory leak, C++ doesn't even tell you what's stored in all that leaked memory.

      That's because you don't need the programming language to tell you that. There are plenty of ways you can make it easy to tell what's in your leaked memory. And then when you're done debugging, you can turn them off and reduce your memory footprint.

    9. Re:Depends by toddbu · · Score: 2, Insightful
      You seem to be under the impression that all GC languages are made by Microsoft.

      Not at all. I was just citing the CLR as one example since it's fairly widely used. You'd also think with all that we've learned about GC on a background thread that Microsoft would have done something different for their new programming environment, but that wasn't the case.

      I never heard of anyone having a GC-related debugging problem (as in real bug, not performance) for programs written in one of those languages.

      Do those languages perform GC in the background, or do they free resources as they're no longer needed? Do they access external resources such as a database, where holding resources can exhaust the available pool, thereby creating artifically scare resources (which is a bug in my book)?

      Most languages that do GC on a background thread have trouble under heavy load because they end up spending lots of time trying to figure out whether they should or shouldn't be cleaning up memory. Also, because most GC systems aren't aware of the difference between physical and virtual memory, they can induce high levels of page faulting even though they think that there's plenty of memory available. Any system that performs GC in the background is going to suck in a high performance environment.

      --
      If you don't want crime to pay, let the government run it.
  3. Mainly GC but sometimes... by 2starr · · Score: 2, Interesting

    In general I prefer having a GC because most of the time I don't want to have to worry about memory management... there's no need. However, sometimes it would really be nice to have more direct control. Not being a VM expert myself, it seems like it should be possible (though I can imagine the types of problems that would arise) to allow specifying that you're assuming manual memory control either over certain objects or while inside a particular context.

    --

    "Let your heart soar as high as it will. Refuse to be average." - A. W. Tozer

    1. Re:Mainly GC but sometimes... by GileadGreene · · Score: 2, Informative
      Except that
      finalize
      is called by the garbage collector right before collection, not automatically invoked when the object goes out of scope.
    2. Re:Mainly GC but sometimes... by emarkp · · Score: 2, Insightful
      What I don't understand is why they couldn't have written Java (and .NET) so we could have our cake and eat it too.
      They have. Visual Studio 2005 adds syntax to Managed C++ (C++/CLI) to allow you to manage your lifetime and memory separately. Herb Sutter has been talking about this for at least a year IIRC. Dinkumware even made the STL work with it.

      See for instance this article. I'm not currently developing on .Net, but I'm hoping that these extensions can be considered at sometime for standard C++. I'm no MS apologist, but it really does seem to be the best of both worlds.

  4. What "performance issues"? by itistoday · · Score: 4, Insightful

    Garbage collection does not equal poor performance. In some instances, it actually speeds things up--when done properly. Take, for example, the D Programming language. It's just as fast as C (faster in some cases) yet it has a garbage collector. The reason is that most programmers tend to not realize that the free() operation actually takes up a decent amount of CPU cycles, and when you're freeing a bunch of little things all over the place, the overhead tends to add up. With a well-designed garbage collector, however, memory is freed all in one big chunk in a single go, and thereby decreasing that overhead. The myth that garbage collection = poor performance is just that, a myth, and most likely started by people who associate Java's performance issues with garbage collection.

    1. Re:What "performance issues"? by be-fan · · Score: 4, Insightful

      In theory C++ custom allocators let the programmer specify the best behavior for any given situation. In practice, very few people use it except for the simple case of pool allocation (which is an optimization you can make in the more sophisticated GC systems). The problem with the C++ mechanism is that it always exposes 100% of the complexity, even in the 99% of the time that you absolutely don't need it.

      --
      A deep unwavering belief is a sure sign you're missing something...
    2. Re:What "performance issues"? by treerex · · Score: 2, Insightful

      The reason is that most programmers tend to not realize that the free() operation actually takes up a decent amount of CPU cycles, and when you're freeing a bunch of little things all over the place, the overhead tends to add up.

      This depends entirely on the underlying memory manager. Using pooled allocation or other "zone-based" allocators can obviate the hit of these frees. As with many things, it's a tradeoff between the time spent putting a block back on its free list (naive implementation) to storing appropriate metadata with each allocated block to "deallocate" it in almost constant time. There is nothing magical about GC here.

      With a well-designed garbage collector, however, memory is freed all in one big chunk in a single go, and thereby decreasing that overhead.

      Sure, memory is freed in one chunk, but you forget the time spent finding unreferenced blocks and copying them (I assume, since you imply blocks are coallesced into one big block).

      The myth that garbage collection = poor performance is just that, a myth, and most likely started by people who associate Java's performance issues with garbage collection.

      Because those of us who have used Java since the mid-90s remember when the first JVM's GC sucked like a giant black whole. I remember at OOPSLA '99 Sun had their GC engineers walking around in garbage man's overalls to show that they were serious about improving GC performance in the language.

      GC performance issues have been around a lot longer than Java, by at least three decades.

    3. Re:What "performance issues"? by Spy+Hunter · · Score: 3, Insightful

      You can't ignore the complexity of manual memory management. You must free all your allocations, and you must police dangling pointers. C++ exposes that complexity all of the time, even though you only need it occasionally, if ever. You can use a smart pointer class, but the more sophisticated of those are simply slow unsafe reference-counting garbage collectors...

      --
      main(c,r){for(r=32;r;) printf(++c>31?c=!r--,"\n":c<r?" ":~c&r?" `":" #");}
  5. Pros and cons by studerby · · Score: 4, Insightful

    As someone who works on long-lived projects with a mid-sized team (a dozen or so developers), I prefer a GC-based language. The biggest pro is the great reduction in memory leaks, closely followed by the productivity increase by not having to think about allocation/deallocation (very much). The biggest con is that far too many "young whippersnappers" seem to think memory allocation/deallocation is therefore "free" in a GC-based language and will take absolutely no care at all about when they allocate (e.g. will allocate a largish object inside a very tight loop instead of allocating it outside and reusing it...). And the 2nd biggest con is that a lot of developers can't believe you can have memory leaks in a GC-based language, won't look for them until you rub their nose in them, and don't really know how to find them when they look.

    --

    .sig generation error:468(3)

    1. Re:Pros and cons by metamatic · · Score: 4, Insightful
      And the 2nd biggest con is that a lot of developers can't believe you can have memory leaks in a GC-based language, won't look for them until you rub their nose in them, and don't really know how to find them when they look.

      I've always thought that the use of the term "memory leak" to describe resource management problems in Java is a really poor choice, as it's quite a different problem from a memory leak in (say) C.

      Keeping memory allocated and referenced for longer than you need it isn't really a leak, to my mind. It's just bad programming. To me, a memory leak is when you lose the pointers to a piece of allocated memory, so the code is no longer able to deallocate it.

      In other words, your developers might give a better answer if you ask "Are there objects you keep around longer than necessary?", rather than "Are there memory leaks?"

      Or maybe I'm the only one.

      --
      GCHQ Quantum Insert installed. If only our tongues were made of glass, how much more careful we would be when we speak
    2. Re:Pros and cons by Keeper · · Score: 3, Insightful

      Unless the language specifies that you can't have circular references between objects, I would consider that broken: the application can get into a state where orphaned objects are not garbage collected.

      Reference counted garbage collection models are inherantly flawed. Leaks are harder to find and easier to provoke. You might as well not have them if you've got to "delete" the references to the other objects.

      Modern garbage collection algorithms do not have this sort of problem.

      What bothers me about garbage collection is that it only solves part of the problem: memory is not the only resource your application holds onto, and the kludges you have to make to deal with them in garbage collected languages are just annoying (hey, you don't have to worry about cleaning up after an allocation ... unless your object has a handle in it; have fun memorizing which objects you have to twiddle with to "release" the resource). If memory didn't have a different release pattern than other resources it wouldn't be a big deal, but ...

  6. Garbage Collection vs. Manual Memory Management by Dual_View · · Score: 2, Interesting
    Manual memory management is similar to assembly language in a certain way: everybody should know how to use it, but they should strongly avoid actually having to use it in most cases. Even though I like to write code in C, I still understand the value of garbage collection. This goes back to the old adage: "Programmer time is more valuable than processor time." On the other hand, there are still a few instances where the manual method is the best tool for the job.

    But then, the question is rather ambiguous. Is the writer asking:

    • "How much does garbage collection affect what language you choose to code in?"
    • "If you were designing a programming language, would you implement garbate collection? If so, what kind? If not, what memory allocation strategies do you use?"
    • "In what situations would you find garbage collection to be the most useful? When is manual memory management better?"

    I'll leave further interpretation of the writer's words to other posters, as well as more thorough responses.
  7. It all depends by unr_stuart · · Score: 3, Interesting

    I've always had the philosophy, "use what makes the job easiest." Typically, this involves garbage-collection. However, one of the biggest problems I have with garbage collection is that you can't have your cake and eat it too. Meaning, you can get all the memory you want, but you can only access it at a high level (think Objects in Java). In C/C++ however, you can call malloc/new, create a big pool of memory (or just a single object), and then do whatever the heck you want with it. But again, as the subject says, it all depends on which method helps get the job done, and so far neither has been perfect for everything.

  8. GC v. Direct allocation by Fubar420 · · Score: 2, Insightful

    As a programmer-come-sysadmin, I vote both. Which has its issues all its own...

    When I programmed professionally, I craved the control of memory management. Objects did _exactly_ what was _explicitly_ told to do.

    Now I'm a ruby junkie, and love the OO, GC, Etc.

    Still, yes, for performance reasons, there are good reasons to do it yourself.

    For programming reasons, there are reasons to go GC.

    all in all, GC tends to be great. wouldnt work without it. But there are times I'm mystified as to why an object left scope, got destroyed, etc.

    So I would (as a programmer), like a compromise [and yes, ruby/rails provides this in its own way, but...] All my objects should be GC'd by default. But I want the ability to hook the destructor, and only have it react the way I expect.

    If I want a big block of memory to manage myself, I find an appropriate object for the language (char *, ruby C bindings to a mempool object, unsafe C# (or even safe C#, if you're good), or whatever idiom matches your lang)

    Then again, you dont get pointers in ruby, so I s'pose I'm just whining...

    So from my perspective:
        - Scripters want GC
        - RAM Intensive code needs at least somewhat programmer-managed MManagement
        - Embedded devices need hard kernel memory management
        - Short run applications generally want GC
        - Long running, RAM intensive, frequent paging, or frequently shifted data process generally should go with kernel malloc.

    Cheers.

    --
    -- (appended to the end of comments you post, 120 chars)
  9. Check this out. by dslauson · · Score: 2, Informative
    There was a pretty good discussion and article on slashdot not too awful long ago about dispelling common myths regarding garbage collection and performance in Java.

    It's definitely worth checking out before people go spouting off the traditional rants against garbage collection.

    Of course, determining which one is best always depends on your application and your available resources, among other things. There are good arguements for both in various situations. I code C++ for embedded devices for a living, which means that I am working with the new/delete/malloc/free model, but for school projects I really like to work with Java, because it lets me focus entirely on implementing an algorithm without having to spend any time thinking about memory allocation or the underlying hardware.

  10. Re:Situational by Jerf · · Score: 4, Insightful

    If security was in question, I might opt for manual memory managment

    Wha? The evidence is against you. It's not the GC'ed languages that have buffer overflows, and that's the number one security flaw at the moment (though #2, "improperly escaped strings resulting in spilling across a boundary", i.e., XSS, SQL injection, etc. is coming up on it fast as more people use GC'ed languages).

    If security is an issue, you want GC and automatic buffer management like Java, Python, Perl, what have you, not manual management and the resulting opportunities for misallocation like in C and C++.

    (Yeah, yeah, if you program perfect C++ code it's possible to get it right. But I'm not talking theory, I'm talking about what happens in the real world, and in the real world, there seems to be quite a supply of less-than-perfect C/C++ programmers allocating buffers. You have to be on crack to argue otherwise.)

  11. C++ and others.... by try_anything · · Score: 5, Interesting

    C++'s constructor/destructor paradigm with predictable object destruction has the benefit of enabling the RAII (Resource Acquisition Is Initialization) idiom. RAII and exceptions greatly simplify resource management in the presence of error handling. Still, even as someone who knows C++ better than I know any other language, I have to admit that for many applications a garbage collected language puts the least mental burden on programmers and produces the fewest memory errors. The burden of arranging all the extra try/catch blocks in Java (because it lacks RAII) has to be weighed against the burden of investigating and fixing memory management errors in C++, and for people using new/delete, Java wins, IMHO.

    C++ programmers should be making very little use of new and delete, though; they should be using smart pointers. I think the article poster misunderstands smart pointers. boost::shared_ptr is a reference counted pointer, but std::auto_ptr and boost::scoped_ptr have nothing to do with garbage collection - they certainly aren't "faked garbage collection" and they certainly aren't unpredictable. They use C++'s object scoping and copying mechanisms to manage memory in a way completely unlike garbage collection. scoped_ptr is the simplest and most predictable memory management tool of all. Taking programmer error into account, it's more predictable than using delete. Even shared_ptr is predictable; when the reference count falls to zero, the object is immediately destroyed, not just marked for destruction.

    Sadly, although C++ is a very powerful language and can be used to write code with few errors, the language as used by beginners is as dangerous as C, perhaps even more dangerous. It takes programmers years to become proficient in all the methods and idioms that make C++ a usable language.

    (I would love to see a language that allows programmers to choose scoped allocation, smart pointer heap allocation, or garbage-collected heap allocation, and uses types to avoid dangerous combinations such as garbage-collected objects pointing to scoped objects or an object pointing to an object in an unrelated scope. Every object would have two types - the object type (int, file, circle, etc.) and the memory management type (scoped with scope S1, scoped with scope S2, garbage-collected, etc.))

    1. Re:C++ and others.... by cryptoluddite · · Score: 2, Interesting

      Why do C++ people use the acronym RAII "resource acquisition is initialiation" to talk about when the object is uninitialized? The acronym is just completely wrong, because languages like Java are far more "RAII" than C++ (in C++ you can actually allocate resources without initializing them). It really should be something more like RAIS, "resource acquisition is scope", or LSILS "lexical scope is logical scope", or ODOL "object destroyed on leaving", or RROL "resource released on leaving", or something that actually makes sense. To me it just sounds like more arbitrary complexity and nonsense, so basically like everything else C++.

  12. usually, I prefer GC by Anonymous Coward · · Score: 2, Informative

    Most new programming languages are using garbage collection

    You mean like Lisp and Smalltalk? ;-)

    The advantages are obvious: programmers no longer have to worry about forgetting to delete allocated memory, leading to far fewer memory leaks.

    In other words: the computer is perfectly capable of figuring out what to do, so let it! This is almost always the best thing.

    When using a manual memory management language, when do you consider the performance and syntactic overhead of faked garbage collection to be worthwhile?

    I haven't used manual memory management in years, except for a couple old C programs that I still maintain (and those are written to be as easy to "visually inspect" as possible.. allocate, use, de-allocate in three separate lines).

    There's rarely good reason to be tinkering around with pointers and other "implementation details". I prefer using very high-level languages (like Haskell for instance) that allow me to express problems and solutions as directly as possible, rather than having to deal with implementation details that only resemble the problem domain from a distance.

    I suppose there are times when you need to override the memory management, so there should definitely be "hooks and hints" where appropriate. And even the highest-level language shouldn't free you from the burden of understanding how computers work. However, I personally haven't needed to know about low-level details in *long* time, not since the Pentium era began at least..

  13. GC by Dr.+Photo · · Score: 5, Informative

    Pros and cons of garbage collection?

    If you don't CONS, you never need to collect garbage. *rimshot*

    More seriously, GC isn't so much about pros and cons, as it is about tradeoffs between the various GC algorithms: time vs. space, low-latency vs. high-throughput, parallelism, etc.

    If you're designing a new language, it should include garbage collection, or nobody will use it (i.e., your target audience can already program in C). You may wish to have multiple GC implementations available for different purposes, perhaps to be selected at compile-time.

    For a good overview of what's available, see http://www.memorymanagement.org/

    My personal favorite is the good old Cheney semi-space collector (and Ephemeral/Generational Garbage Collectors, which are more advanced versions designed to generally have low latency), as it is very straightforward (both to understand and to implement), compacting (it defragments memory, and can perhaps improve cache locality by grouping related objects), and it has high throughput (work is proportional to the amount of live data, not total data).

    If memory usage is of more concern than fragmentation and throughput, a mark-sweep collector may be more your style.

    There are also "real-time" (and "soft-real-time", i.e. bounded latency [see Henry Baker's Treadmill]) collectors, parallel collectors [including an interesting case for reference counting, usually considered a dog performance-wise, as a viable parallel/remote GC method], "conservative" collectors for C/C++ (see Hans-J Boehm's libgc), collectors for real and hypothetical computers with special hardware and/or OS support for GC features, and some collectors that are just plain weird.

    Note also that garbage collection algorithms are considered hard to measure for performance, especially with regard to wall-time latency, so just because a paper(*) claims that a certain GC has certain performance characteristics, be sure to benchmark if it really matters.

    (*) Did I mention papers? If you're serious about implementing GC, getting comfortable reading CS research papers is a must. The book "Garbage Collection" is your best friend here, as it provides a very good overview/survey of said papers and algorithms, and it discusses a lot of pros and cons between various algorithms, and useful variants or adaptations that have been applied to previously-published work.

    Also check out Henry Baker's papers, because he is a memory management demigod: http://home.pipeline.com/~hbaker1/home.html.

  14. Memory Access vs. Memory Allocation Re:Situational by hackwrench · · Score: 2, Informative

    People seem to have confused Memory Access with Memory Allocation. Neither GC nor PC (programmer collected) should allow memory accesses on out-of-scope data. GC just delays when that out-of-scope data gets freed for reallocation. Those unfamiliar with GC and used to the unreallocated = still-accessible-data situation of improper PC coding think that in the GC world unreallocated means still-accessible, which is not necessarily nor usually the case.

  15. Cocoa and Objective-C by mccoma · · Score: 2, Interesting

    Apple / NeXT takes a reference counting approach. It is not automatic, but it works well once you understand the rules.

    1. Re:Cocoa and Objective-C by feijai · · Score: 2, Insightful

      As an old Obj-C coder, let me respectfully disagree with this. Reference counting does not handle cycles: that's a huge flaw. It forces Apple to promote a notion of "ownership" of object graphs which only works on a small scale. It does not work well: it merely reduces what you need to keep track of (but doesn't eliminate it) in return for a considerable amount of manual labor.

  16. RAII is a bad reason for manual memory management by GileadGreene · · Score: 3, Insightful

    All of the reasons given for manual memory management seem to boil down to a desire to have support for the Resource Acquisition Is Initialization (RAII) idiom, which is hard to pull off in GC languages. But, the alternative idiom Resource Acquisition Is Invocation provides the desired capability in GC languages. Same capability, no chance of memory leaks. So tell me again why manual memory management might be a good idea?

  17. Explicit management has its own costs by Pseudonym · · Score: 4, Insightful

    The answer, as always, is "it depends". I'm firmly inside the "right tool for the job" camp.

    Manual memory management is not free. In some circumstances, it can be quite expensive. There is a group of programmers who are best described as "rabidly anti-GC". These people are almost all completely unaware of the costs that manual memory management can impose on your code.

    A multi-threaded program, for example, can allocate memory from any arena, but it MUST return a block to the arena from whence it came, which can cause all sorts of difficult lock contention problems, making free() much more expensive than malloc(). (Ask anyone who has written high-performance memory-intensive multi-threaded programs.)

    In some languages, like C, the situation is even worse. In structure-hungry programs, you can end up structuring your code around data lifetimes, which precludes you from using the most natural, maintainable and efficient algorithms. Garbage collection frees you from this, as the GCC people have discovered.

    I do recommend reading Paul Wilson's excellent survey paper on the topic. It answers a lot of your questions, though it's by no means the final word.

    --
    sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
  18. Re:If C++ Memory Management by try_anything · · Score: 2, Interesting

    I agree with a comment posted elsewhere that unchecked memory access and manual memory management, while both unsafe and fertile sources of errors, are different beasts.

    Manual memory management is a control issue. Unchecked memory access is a matter of asceticism.

    Buffer overruns happen because the devotion to performance and minimalism among a certain crowd is religious. Because of this, the C++ standards guys were terrified of encouraging the use of anything slower and safer than what a C programmer would do. In std::vector and boost::array the default (and readable) access operator [] is unchecked, and checked access is relegated to the ugly at() method. This is a political decision that turns on its head the principle that quiet syntax should be used for routine, safe operations and ugly syntax should be used for rare, dangerous operations.

    Using template metaprogramming, it's easy to produce your own array classes with bounds-checking chosen at compile time, but because the survival of C++ depended on the "just as fast as C!" slogan, unchecked access was officially encouraged and has unsurprisingly become the norm among C++ developers.

    Rationally, even a developer who expects that bounds checking will always be too expensive in production should insist that bounds checking be easily enabled at compile time. Electric Fence helps with that, but template metaprogramming is a more straightforward solution.

  19. not true by doug · · Score: 2, Funny
    The myth that garbage collection = poor performance is just that, a myth, and most likely started by people who associate Java's performance issues with garbage collection.
    Sorry, but I've thought GC was slow since the 80s. Java had nothing to do with it. - doug
  20. GC is DRY by PBPanther · · Score: 2, Interesting

    Not using GC requires that you to write code to free those resources repeatedly. That goes against the DRY (Don't Repeat Yourself) principle.

    I wonder how many of the people who use the "C++ model" bother to unit test that they have freed all their resources.

  21. C has problems too by countach · · Score: 2, Informative

    C memory management is not completely deterministic either, since a fragmented heap will not always take the same amount of time to allocate in. To make it completely deterministic you would have to pre-allocate objects. But if you're going to do that, you could do it in a GC language and turn the GC off.

    1. Re:C has problems too by be-fan · · Score: 4, Insightful

      It's frightening the allusions programmers have about manual memory management. They seem to think that malloc() and free() are cheap functions, when in reality they can take hundreds of clock cycles. They think that malloc() is deterministic, when in reality, a badly fragmented freelist can cause most malloc() implementations to traipse through the entire heap, just like a GC.

      The weirdest thing is C++ programmers. They freak out about every single cycle, but modern C++ idioms push the use of smart pointers, which are usually quite slow compared to a good generational GC.

      --
      A deep unwavering belief is a sure sign you're missing something...
  22. There's more than one way to skin a cat. by Anonymous Coward · · Score: 2, Informative

    Having used languages with and without garbage collection, my view is that
    garbage collection is often very nice... but I don't really mind the "lack" of garbage collection in C and especially don't miss it in C++.

    My opinion is that it takes some effort on the programmer's part to learn to use C safely. I'm not sure why, but this answer seems to suprise some people. Do they seriously expect that in the real world-- of software or of anything else-- that they should be able to pick up any tool they want and understand how to use it well right away? Appearantly so, but it's pretty silly, isn't
    it?

    C++ and C are like very sharp carving gouges: It's up to you to learn how to use them properly, to hone them peridically, and to build safe habits. You need to do this in any language that you use, but the sharper the tool the more important it is to bear this principle in mind. A lot of people try to pick up these sharp tools, and then blame the gouge when they've cut themselves. It's no suprise, because they did not take the time to learn to be careful.

    In my view your best bet for using a programming language safely is to develop
    certain habits and adopt idioms that cause you to simply not write code with some types of errors. In the case of resource-freeing errors, when you open a door, you must remember to close it. It's not complicated, but you have got to turn it into a real habit, something you just do-- and it follows that there will also be some patterns that you should train yourself to just never write. Give it a go (and give it some time).

    That will go a long way, but I'm afraid that there's some bad news: even that is not enough. I've been writing software in C for 17 years now, and although without a doubt I write fewer errors than I used to, I still do not produce error-free programs. Eventually, I make plenty of mistakes. Complexity does that.

    Some very good news: Memory management in C++ is so nice that very frankly I do not miss /either/ garbage collection or C-style memory management when I am using it. (And of course, you can use either of those with C++ just fine.) There are all kinds of tools and patterns to help you out, although again it's going to be up to you to use them and make a habit of it. There's the "resource aquisition is initialization", smart pointers (built into the standard library, provided by Boost, and roll-your own), new and delete, malloc() and free(), statically allocated memory, and garbage collectors for you to link in. Take your pick! Use the right one for the job.

    Bjarne Stroustrup explains all of this extremely well. Here's a link or two to his FAQ and what it has to say about C++ and garbage collection:

            http://www.research.att.com/~bs/bs_faq.html#garbag e-collection
            http://www.research.att.com/~bs/bs_faq2.html#memor y-leaks
            http://www.research.att.com/~bs/bs_faq.html#advanc ed

    Think about it for a while. Remember that memory is only one kind of resource that we need to manage. It's up to you to ferret out and apply the tools available to you.

    If you want a garbage collector, why not use one? But it's not the only way to achieve the ultimate goal of producing reliable, efficient software.

  23. Re:Getting it backwards by Profound · · Score: 2, Interesting

    >> you can write "destructor's" in a garbage collected language

    You mean like Java's Object.finalize()?

    The same one that causes significant performance problems fundamental to how GCs work, and is not guaranteed to execute in any specific order, or even at all?

  24. Personally... by g-san · · Score: 3, Funny

    I prefer garbage collection. At most, I take the cans to the edge of the driveway and some guy in a noisy truck with a cool robotic arm just hauls it away. Yeah, there is a landfill somewhere that isn't good for the overall environment but I accept that tradeoff. I also don't throw old car batteries into the trash.

    Sure the hell beats me keeping the trash around, remembering where it is, and putting it in my truck and hauling it to the heaping landfill myself. I'm not here to manage trash, I'm here to get something done.

    Is this post about programming?

  25. False dichotomies by Eric+Smith · · Score: 3, Interesting
    Some of the cited advantages of not using garbage collection are red herrings. For instance the "controlling access to files and similar resources" by RAII works fine with garbage collection. In most cases, the compiler can determine by static analysis that a particular object is allocated within a scope and no referenes are propogated upward out of scope, and can remove the reference so the garbage collector will deallocate it (possibly calling a destructor). Depending on the type of GC and its implementation, the compiler may generate code that forces the object to be deallocated immediately.

    For cases where static analysis can't do this automatically, it isn't that hard to use a design methodology that achieves the same result; it's certainly still much easier than doing manual allocation and deallocation and ensuring that the deallocation is done (or not done) correctly in all cases.

    And if you are using a reference-counting GC, or a hybrid GC that includes reference-counting, you don't have to do anything special at all.

    The same applies to the claimed mutex and error message disadvantages, since those are just specific uses of RAII.

  26. Java GC != No leaks by samjam · · Score: 2, Insightful

    Right now someone I know is trying to track down a Java memory leak.

    No doubt some reference is left in a persistent collection of some sort (hash, list, array, etc)

    Just As C/C++ programmers must remember to free when done, so Java programmers must remember do undo such "life maintaining" references when they are done.

    Sam

    1. Re:Java GC != No leaks by the+eric+conspiracy · · Score: 3, Insightful

      Right now someone I know is trying to track down a Java memory leak.

      Yes, but it is unlikely that somebody you know is trying to track down a Java double free error.

  27. Garbage collection efficiency overstated by butlerm · · Score: 3, Interesting

    This is a common claim, but it is an apples to oranges comparison. No one (including the compiler) dynamically allocates objects in C/C++ when they can place them on the stack instead. Garbage collected languages like Java, on the other hand, require practically everything to be managed on the heap.

    In addition, an array of objects on the heap requires only a single memory allocation in C or C++, where Java has to allocate and track each separately. As one luminary once said, "C++ is better because there is less garbage to collect."

    That might be acceptable, but the worst part is random application pauses of arbitrary duration for garbage collection. Unless that problem can be resolved, garbage collected languages will be always be a poor match for latency sensitive applications, even where the net throughput is otherwise adequate.

    1. Re:Garbage collection efficiency overstated by swillden · · Score: 4, Interesting

      No one (including the compiler) dynamically allocates objects in C/C++ when they can place them on the stack instead.

      Are you certain of that? Here:

      void foo()
      {
      //...
      auto_ptr<Foo> f(new Foo);
      //...
      };

      What would the compiler do? What *could* it do, if it were smarter? And have you really never seen any code that does this? Or written it?

      Lots of C and C++ programs dynamically allocate many objects that could be heap allocated. In particular, many C++ objects that are placed on the stack immediately allocate storage on the heap. Think std::string. Many programmers do make an attempt to allocate as much on the stack as possible, but I think most don't really consider it. And keep in mind when I say this that I've been writing C and C++ (mostly C++) professionally for nearly 15 years -- I've seen more than a little code.

      Garbage collected languages like Java, on the other hand, require practically everything to be managed on the heap.

      Interestingly, Java does *not* require that at all... it's just the most obvious way to implement it. In fact, I read a while back that the next generation of Java compilers will perform escape analysis, looking for objects whose lifetime is associated with a stack frame. Here's a link. When they find such an object, it will be allocated on the stack. If such an object creates other objects, as long as the analysis can prove that their lifetimes are also frame-associated, they will also be allocate on the stack.

      The same analysis will often allow Java objects and their sub-objects to be allocated as a single block. Since the compiler can see that the constructor of class Foo always allocates objects of Bar and Baz, all of fixed size, it can allocate a single block, just like a C++ compiler would be able to for a class like:

      class Foo
      {
      // ...
      Bar bar;
      Baz baz;
      };

      The same sort of analysis should also allow your other point to be addressed: An array of objects can be allocated as a single block. The compiler can recognize code like:

      Foo[] f = new Foo[n];
      for (int i; i < n; ++i)
      f[i] = new Foo;

      And allocate a single block that is n*(sizeof(Foo)+sizeof(Bar)+sizeof(Baz)) in size, and if 'f' has a stack-associated lifetime, allocate the whole pile on the stack.

      All of the above is still theoretical, of course, but it's coming quickly.

      That might be acceptable, but the worst part is random application pauses of arbitrary duration for garbage collection. Unless that problem can be resolved, garbage collected languages will be always be a poor match for latency sensitive applications, even where the net throughput is otherwise adequate.

      As I pointed out in my previous post, whether or not that problem exists depends on the GC implementation. Incremental GCs keep the pauses small, and there are GCs designed for real-time usage that further guarantee maximum latencies. It's worth pointing out also that normal malloc() and free() implementations don't provide any run-time guarantees. Real-time code that uses a heap uses special versions that do provide guaranteed latencies, at the expense of worse average performance.

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
  28. VM aware GC by renoX · · Score: 2, Interesting

    A paper I've found interesting is on a GC which communicates with the VM systems to avoid putting too much load on the VM system.
    It needs a modification of the VM, but IMHO this is better than having to handtune the memory used by the GC. (Note: I'm not an expert in GC)

    http://www.cs.umass.edu/~emery/pubs/04-16.pdf

  29. Lisp idiom by Nicolay77 · · Score: 2, Interesting

    In lisp that would be using the unwind-protect macro.

    Notice that this is totally unrelated with memory management.

    So yes, it IS possible to have our cake and eat it too.

    --
    We are Turing O-Machines. The Oracle is out there.
  30. Re:The first GC language ever, does it... by Nicolay77 · · Score: 2, Informative

    You're absolutely correct, however...

    You don't usually use unwind-protect directly. You use a macro that uses it underneath. Like the with-open-file macro or the with-database macro of CLSQL.

    Like this:

    (with-open-file (stream "/some/file/name.txt")
        (format t "~a~%" (read-line stream)))

    You can never forget to close the file in that code.

    Having to use unwind-protect directly is just another case of the "human compiler" pattern at work. It's very unusual to have to use database access or file access or something like that just once in your program, so writing a macro is a good investment.

    --
    We are Turing O-Machines. The Oracle is out there.
  31. Re:RAII is a bad reason for manual memory manageme by GileadGreene · · Score: 2, Insightful

    As some of the folks at C2 pointed out in the originally linked references, RAIInitialization is a misnomer anyway (as is RAIInvocation - but that was created in response to the other RAII). Most of what we're talking about here is (despite the name) finalization. That's the part that conflicts with GC. No one's saying that we should eliminate initialization or constructors. The point is that using the RAIInit idiom to handle resource finalization is not a good argument for manual memory management, because the RAIInvoc can produce the same finalization effects without producing any conflict with garbage collection.