13

Do any languages really need garbage collection? Is there not a way to figure out when a object should be destroyed? I haven't had leaks in C++ and i dont use smart pointers or reference counters or anything special. I confirm this by attaching something for leak detection: whether its built in to the IDE or a header that uses magic (defines) to overloads new/free.

Is garbage collection necessary, or is it possible to have a leak-free application in a language without placing the memory burden on the programmer?

10 Answers10

23

Is there not a way to figure out when a object should be destroyed?

The short answer is no. It is not possible for compilers to figure out at compile time when objects need to be freed, in the general case.

Consider the following pseudo-code:

def my_function(some_input):
    A = allocate_some_object(some_input)
    B = allocate_other_object(some_input)
    if check_some_condition(A, B):
        return A
    else
        return B

In order for the compiler to know whether A or B should be freed after this function returns, it has to know what check_some_condition(A, B) will return. That would require solving the halting problem, which is not possible in the general case.

More seriously, check_some_condition could store a reference to A somewhere else, in which case A is not garbage at the end of the function even if B is returned. The compiler would have to be able to know whether this happens with 100% certainty, and even if it did know you then have to solve the problem of flowing the information around until you find some place where A does become garbage and can be deallocated. That could be in a completely different part of the program.

Plus, deallocating every object as soon as it becomes possible isn't actually always the best option. If objects are being created and dropped all the time, and you have enough memory available, running a garbage collector every so often and deallocating the garbage in bulk can actually be more efficient than hand-tuned C-style manual memory management (despite claims that GC is always a trade off between performance and convenience).

There are techniques that can do some of this, some of the time. Escape analysis can allow the compiler to deduce that a given object cannot "escape" some section of code, so what looks like a heap allocation can be turned into a stack allocation, which is effectively memory managed by the compiler. I've read about other techniques allowing a compiler to tell that a given object must be garbage at the point another object of the same size is created, so instead of compiling an allocation of a new object it re-uses the dead value. But it simply isn't possible to completely replace garbage collection cycles with the compiler figuring out statically when every object needs to be deallocated, because the compiler can only figure that out some of the time.

Ben
  • 1,027
  • 7
  • 10
  • Very good. I want to pick a few points 1) if it was recursive and its only true in the base case why would the gc free the memory? How would it know the if statement wont execute 2) i heard many memory managers in C are bad. As in they do all the bookkeeping on every delete and new instead if flip a few flags and run them in bulk. I dont suppose gc can do them faster if the memory manager tries to free in bulk? –  Oct 09 '11 at 02:39
  • If "the compiler figuring out statically when every object needs to be deallocated" why is it not possible "to completely replace garbage collection"?
  • –  Oct 09 '11 at 02:41
  • @acidzombie24 1) I think I framed that example very badly. What I was trying to do was make you think of a case where a heuristic static memory manager would get it wrong and have to keep excess memory around, where a dynamic garbage collector would prevent unbounded memory growth. Such cases exist; I just failed to demonstrate one. – Ben Oct 09 '11 at 03:05
  • @acidzombie24 2) The essential difference is that by reacting to objects dropping out of scope then you need at least some operations for every object you free even if that's just flipping a few flags and then the amortized cost of the bulk deallocate (although you probably can't bulk deallocate in C; the objects will be non-contiguous). A fully managed GC scans the live objects, and can compact the heap as it goes. So the final deallocate is just a single pointer subtraction, and the scan only considers live objects, and only on each GC cycle. For some workloads this can be less work. – Ben Oct 09 '11 at 03:18
  • @acidzombie24 And 3) my point was that it is not possible for the compiler to figure out statically when every object needs to be deallocated. There's always cases that require information from runtime to do properly, so if the compiler were doing it statically it would have to use conservative safe assumptions. And that means there'll always be cases where those rules aren't good enough, and the program uses too much memory, while a GC would let it run fine. – Ben Oct 09 '11 at 03:20
  • @acidzombie24 There, I've updated my example of "undecidable garbage" to be a lot clearer, I hope. – Ben Oct 09 '11 at 03:27
  • 2
    The return value of check_some_condition(A,B) is irrelevant for determining when to free A or B, at least for this example. The compiler could trivially insert frees: if check_some_condition(A,B) { free B; return A } else { free A; return B }. The problem here is if check_some_condition(A,B) stores references to A or B anywhere. – 8bittree Jun 17 '16 at 19:42
  • "The short answer is no. It is not possible for compilers to figure out at compile time when objects need to be freed, in the general case."

    I just want to add one comment, your answer is completely stupid if not borderline retarded. The code you have mentioned works today in rust https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2986b67e9c80a79a7f50ec416b5b40cf and I'm so sick of people on the internet, out of their own ignorance saying "something is impossible" when they have no clue what they're talking about. Your attitude limited research and creativity at 2011.

    – Vanilla Face Jan 11 '19 at 11:05