Do I still need to learn about managing memory now that Objective-C/Cocoa has Garbage collection? - objective-c

So I finally dusted off my Objective-C/Cocoa books.. turns out they are nearly 7 years old! With Objective-C 2.0 now having garbage collection, how important are the chapters on Memory Management?
How much of a difference has Garbage Collection made?

Memory management is still really important to understand. If you're targeting an older OS, you need to do memory management. If you're using an older library, you need to do memory management. If you drop down to the Core Foundation level, you (may or may not) need to do memory management.
If you're programming for iPhone, you need to do memory management.
The garbage collector in Objective-C is outstanding - and if you can be using it, you most definitely should be - but it just doesn't cover every programming situation yet.

Some Cocoa technologies, such as Distributed Objects, PyObjC (the Python-Objective-C bridge) plugins and CoreImage (at least last I heard; this may have been fixed) don't play well with Garbage Collection. If you're using these technologies, you will still have to use traditional memory management. Of course, as others have said, you still need to use traditional Cocoa memory management (reference counting) if you're supporting OS X 10.4, or the iPhone in your code.
On the other hand, the new GC can be very nice. It's not a free lunch however; you still need to understand the semantics of the GC system, its patterns and its limitations...just as you do with any technology.
Since many thrid-party frameworks may not yet support GC, it's probably best to still understand the reference counting system. If you follow the simple rules for object ownership given in Apple's memory management guide, you should always be OK.

If you're programming the iPhone platform, you need to know retain/release, because Cocoa Touch does not have GC.
If you're going to use Core Foundation, Core Graphics, most of Core Services, or any other CF-based API, you need to know retain/release, because CF-derived objects are not GC'd by default (and you must explicitly put them out for pick-up, anyway).
If you're going to use any of the POSIX APIs or any of the rest of Core Services, you need to know alloc/free memory management. You don't even get reference-counting. (Exception: Icon Services, which also has reference-counting. APIs born from Carbon are a mess.)
So, in a word: Yes.

It depends. If you're planning on ignoring 10.4 users, then you might not have to worry about it; but Objective-C 2.0 isn't available on 10.4 and below, so you still have to worry about memory management on those platforms.
That said, memory management is always a useful skill, and it's not that hard in Cocoa anyway, so it's not a bad skill to pick up.

It is probably worth learning about the concepts that underpin Cocoa memory management, as it's still useful in certain situations. The iPhone OS, for example does not support garbage collection. There may be other situations where it is advantageous to use manual memory management, and it's useful to have the ability to make that choice

Understanding Cocoa's excellent memory management concepts will help you with the concept of memory management in general. I've copied the autorelease concept into a few C++ projects and it worked great. Apache and Subversion are examples of other software that also uses autorelease.
Personally I find retain/release/autorelease to be just the right level of abstraction for me. It's not magic, so if I really need to do something weird, it's easy to do so. On the other hand, the rules are so simple that it becomes second nature, to the point where you eventually just don't think about memory management anymore, it just works.
Add to this the fact that, as mentioned above, only most of Cocoa supports garbage collection, while what you are writing is C, so any code you write and/or use that isn't Cocoa will need to be manually managed. This includes CoreAudio, CoreGraphics, and so on.
(Yes, CF objects work with GC, but only if you explicitly enable it for each object, and I found it hard to learn the GC-CF rules)
In summary: I never use the garbage collector myself (and the only time I did so it was very painful, as I had some C++ and CG in the mix), and as far as I know, most Cocoa coders are very used to retain/release/autorelease and use that.

Related

Is garbage collection used in production quality Cocoa apps?

I'm mainly wondering about the affect that garbage collection would have on performance. Is the use of garbage collection frowned upon for release apps?
Another concern that I can think of is that using garbage collection could lead to sloppier programming.
Do you use garbage collection in your apps?
Garbage Collection is used in many production quality applications. Xcode, Automator, System Preferences and several other system applications are GC'd, and you can expect that trend to continue over time.
As well, many developers have embraced GC and are using it exclusively in their applications. Intuit's new versions of Quicken and QuickBooks for the Mac are garbage collected, for example.
There are a number of advantages of GC, too. Off the top of my head and from personal experience:
it makes multithreading easier; a simple assign is an atomic declaration of ownership
it offloads a bunch of memory management to other cores; it is naturally concurrent and offloads a bunch computation from the main thread (or computation threads)
in many cases, allocation and deallocation can happen entirely within the context of a thread, thus eliminating any need for global synchronization or locking
the collector has gotten faster with each release of Mac OS X and that trend will continue (just as it has with the rest of the system). By offloading more of your app's computational load to the system provided frameworks, your app will gain more and more from optimizations to the underlying system.
because the collector has intimate knowledge of the object graph -- of the pointers between objects -- in memory, it makes analysis and debugging significantly easier. Instead of "where did this dangling pointer come from?", the question is now "Give me a list of reasons why this object is sticking around longer than I think it should?".
This isn't to say that there isn't work to do to make your application work optimally under GC. There certainly are such tasks!
Garbage collection has been around since the 1960s and is used in many released applications. All .NET apps use garbage collection. Apple uses libauto in Xcode.
Garbage collection generally leads to better quality apps in Cocoa since the developer is freed from the memory management burden. There are tons of Cocoa apps that leak! (though it may not a significant amount of memory)
I tend to use gc since since I can turn around my apps faster and don't have to worry about messaging zombie objects!
I use GC whenever I can, because the best code of all is the code you don't have to write in the first place. Also, as Bbum pointed out above, running under GC means that you have far more information available for performance analysis, should you need to debug any bottlenecks.
Garbage collection is recommended for any new Cocoa applications, and Apple eats its own dog food by using it in Xcode. Performance is an interesting situation, because while you're most likely going to be consuming more CPU cycles overall, the application may actually end up faster in some areas due to multithreading of the collector and the simplification of accessor methods.
Computers are made to do work for us. Cocoa's reference counting is usually easy to manage, but garbage collection is one more thing it can do now--let the machine do the work so you can focus on things that matter!
Like the others, I would strongly recommend using GC. The performance overhead usually is negligible! I don't need to repeat the benefits as stated by other users.
However, I would strongly encourage writing libraries, as opposed to applications, to run in a non-GC mode as well. Some environments cannot run GC code, the iPhone being the notable one; so if you created an internal library for yourself, that you envision reusing it later for an iPhone app, then I would recommend designing it so it would work in a non-GC environment as well.
Converting a GC code to non-GC code is much more difficult than the other way around!

Getting Embedded with D (the programming language)

I like a lot of what I've read about D.
Unified Documentation (That would
make my job a lot easier.)
Testing capability built in to the
language.
Debug code support in the language.
Forward Declarations. (I always
thought it was stupid to declare the
same function twice.)
Built in features to replace the
Preprocessor.
Modules
Typedef used for proper type checking
instead of aliasing.
Nested functions. (Cough PASCAL
Cough)
In and Out Parameters. (How obvious is that!)
Supports low level programming -
Embedded systems, oh yeah!
However:
Can D support an embedded system that
not going to be running an OS?
Does the outright declearation that
it doesn't support 16 bit processors
proclude it entirely from embedded
applications running on such machines? Sometimes you don't need a hammer to solve your problem.
Garbage collection is great on Windows or Linux, but, and unfortunately embedded applications sometime must do explicit memory management.
Array bounds checking, you love it, you hate it. Great for design assurance, but not alway permissable for performance issues.
What are the implications on an embedded system, not running an OS, for multithreading support? We have a customer that doesn't even like interrupts. Much less OS/multithreading.
Is there a D-Lite for embedded systems?
So basically is D suitable for embedded systems with only a few megabytes (sometimes less than a magabyte), not running an OS, where max memory usage must be known at compile time (Per requirements.) and possibly on something smaller than a 32 bit processor?
I'm very interested in some of the features, but I get the impression it's aimed at desktop application developers.
What is specifically that makes it unsuitable for a 16-bit implementation? (Assuming the 16 bit architecture could address sufficient amounts of memory to hold the runtimes, either in flash memory or RAM.) 32 bit values could still be calculated, albeit slower than 16 bit and requiring more operations, using library code.
I have to say that the short answer to this question is "No".
If your machines are 16 bit, you'll have big problems fitting D into it - it is explicitly not designed for it.
D is not a light languages in itself, it generates a lot of runtime type info that normally is linked into your app, and that also is needed for typesafe variadics (and thus the standard formatting features be it Tango or Phobos). This means that even the smallest applications are surprisingly large in size, and may thus disqualify D from the systems with low RAM. Also D with a runtime as a shared lib (which could alleviate some of these issues), has been little tested.
All current D libraries requires a C standard library below it, and thus typically also an OS, so even that works against using D. However, there do exist experimental kernels in D, so it is not impossible per se. There just wouldn't be any libraries for it, as of today.
I would personally like to see you succeed, but doubt that it will be easy work.
First and foremost read larsivi's answer. He's worked on the D runtime and knows of what he's talking about.
I just wanted to add: Some of what you asked about is already possible. It won't get you all the way, and a miss is as good as a mile here but still, FYI:
Garbage collection is great on Windoze or Linux, but, and unfortunately embedded apps sometime must do explicite memory management.
You can turn garbage collection off. The various experimental D OSes out there do it. See the std.gc module, in particular std.gc.disable. Note also that you do not need to allocate memory with new: you can use malloc and free. Even arrays can be allocated with it, you just need to attach a D array around the allocated memory using a slice.
Array bounds checking, you love it, you hate it. Great for design assurance, but not alway permissable for performance issues.
The specification for arrays specifically requires that compilers allow for bounds checking to be turned off (see the "Implementation Note"). gdc provides -fno-bounds-check, and in dmd using -release should disable it.
What are the implications on an embedded system, not running an OS, for multithreading support? We have a customer that doesn't even like interrupts. Much less OS/multithreading.
This I'm less clear on, but given that most C runtimes allow turning off multithreading, it seems likely one could get the D runtime to disable it as well. Whether that's easy or possible right now though I can't tell you.
The answers to this question are outdated:
Can D support an embedded system that not going to be running an OS?
D can be cross-compiled for ARM Linux and for ARM Cortex-M. Some projects aim at creating libraries for Cortex-M architectures like MiniLibD for the STM32 or this project which uses a generic library for the STM32. (You could implement your own minimalistic OS in D on ARM Cortex-M.)
Does the outright declearation that it doesn't support 16 bit processors proclude it entirely from embedded applications running on such machines? Sometimes you don't need a hammer to solve your problem.
No, see answer above... (But I would not expect that "smaller" architectures than Cortex-M will be supported in the near future.)
Garbage collection is great on Windows or Linux, but, and unfortunately embedded applications sometime must do explicit memory management.
You can write Garbage Collection free code. (The D foundation seems to aim at a "GC free compliant" standard library Phobos but that is work in progress.)
Array bounds checking, you love it, you hate it. Great for design assurance, but not alway permissable for performance issues.
(As you said this depends on your "personal taste" and design decisions. But I would assume an acceptable performance overhead for bound checking due to the background of the D compiler developers and D's design aims.)
What are the implications on an embedded system, not running an OS, for multithreading support? We have a customer that doesn't even like interrupts. Much less OS/multithreading.
(What is the question? One could implement mutlithreading using D's language capabilities e.g. like explained in this question. BTW: If you want to use interrupts consider this "hello world" project for a Cortex-M3.)
Is there a D-Lite for embedded systems?
The SafeD subset of D targets at the embedded domain.

When implementing an interpreter, is it a good or bad to piggyback off the host language's garbage collector?

Let's say you are implementing an interpreter for a GCed language in a language that is GCed.
It seems to me you'd get garbage collection for free as long as you are reasonably careful about your design.
Is this generally how it's done? Are there good reasons not to do this?
Language and runtime are two different things. They are not really related IMHO.
Therefore, if your existing runtime offers a GC already, there must be a good reason to extend the runtime with another GC. In the good old days when memory allocations in the OS were slow and expensive, apps brought their own heap managers which where more efficient in dealing with small chunks of data. That was one readon for adding another memory management to an existing runtime (or OS). But if you're talking Java, .NET or so - those should be good and efficient enough for most tasks at hand.
However, you may want to create a proper interface/API for memory and object management tasks (and others), so that your language ("guest") runtime could be implemented on to of another host runtime later on.
For an interpreter, there should be no problem with using the host GC, IMHO, particularly at first. As always they goal should be to get something working, then make it work right, then make it fast. This is particularly true for Domain Specific Languages (DSL) where the goal is a small language. For these, implementing a full GC would be overkill.

Is Objective C A Suitable Language For 3D Games?

I see a lot of debate going back and forth on which language to use to develop real-time 3D games, and the general consensus is that C or C++ are the only languages that can offer suitable performance for high-end, system-intensive 3D games. I see a lot of people saying C#, Java or Python are too slow, particularly because of garbage collection. How about Objective C? Does Objective C have automatic garbage collection? What besides Automatic Garbage Collection make a language 'too slow' or unsuited for 3D games?
This question is probably more of a 'thought experiment' since I doubt I'll ever develop a game that is so resource heavy that these questions need to be addressed, but being a programmer, I'm inexplicably obsessed with performance, so I'd still like to know just for my own jollies.
Objective-C 2.0 has garbage collection available on Mac OS X 10.5, but it is optional -- you can still compile Objective-C apps without garbage collection if you so choose. On other platforms (iPhone, Mac OS X pre-10.5, and anything else), there is no garbage collection, and you have to manually manage your memory.
Objective-C is a strict superset of C, so you can code plain C in Objective-C if you want. Hence, there's no reason not to use Objective-C for games that wouldn't also apply to using C. You can use the extra features Objective-C provides as much or as little as you want.
The only real slowdown with Objective-C itself would be the messaging mechanism—and even then, it's usually components of the Cocoa framework that would slow things down. Objective-C's message sending doesn't really hurt performance that much.
Anyways, for most games, the majority of the performance bottlenecks will come from graphics code: if you delegate graphics stuff to OpenGL, which is ridiculously fast, then there really should be no problem with using Objective-C for games. The only other place where I can see Objective-C or Cocoa providing bottlenecks would be for intensive physics code—and that should probably be written in pure C/C++ anyways. Everything else, though, shouldn't really matter that much.
To be honest, I'd wager that the majority of OS X games nowadays are written in Objective-C using the Cocoa frameworks, with the performance-sensitive code written in pure C/C++ (and with graphics code utilizing OpenGL).
I'm also interested in the topic and i found this
http://wiki.gnustep.org/index.php/3DKit
It looks quite dead but now with clang/llvm 2.9 many of the goodies of Objective-C 2 are available on linux and could be interesting to have 3D API.
Objective-C does not have automatic garbage collection. Java has various methods of garbage collection and some of them are designed to be compatible with games by occurring incrementally at regular intervals. I would be surprised if C# or anything else which also had garbage collection didn't have multiple methods to choose from, some of which are compatible with games.
The only thing off the top of my head that would might make a game unsuitable for 3D games would be if it were interpreted and particularly slow in its implementation. That's not a characteristic of anything you listed above.
P.S. To address your original question, I'm pretty sure anyone who has an iPod Touch or iPhone will be able to tell you that Objective-C is definitely up to 3D games :)

What are alternatives to Objective-C for Mac programming?

I've become very comfortable in the world of pointer-free, garbage-collected programming languages. Now I have to write a small Mac component. I've been learning Objective-C, but as I confront the possibility of dangling pointers and the need to manage retain counts, I feel disheartened.
I know that Objective-C now has garbage collection but this only works with Leopard. My component must work with Tiger, too.
I need to access some Cocoa libraries not available to Java, so that rules out my usual weapon of choice.
What are my alternatives? Especially with no explicit pointers and automatic garbage collection.
What do you mean by "component?" Do you mean a chunk of code or a library you are going to hand to other people to link into their apps? If so then it is not realistic to use any of the bridged languages at this time. While a lot of the bridges are very nice, they almost always have complications and issues that most app developers will not be willing to deal with to use a single component, especially if it involves bringing in a substantial runtime.
The bridges are most valuable to bridge other language libraries into your Objective C app. While you can write fairly complete apps using them, doing so often requires a better understanding of Objective C than simply writing an Objective C application, since you need to understand and cope with the language, object model, threading, and memory allocation impedance mismatches that occur.
This is also why many people argue that even if you are quite familiar with a language, trying to learn Cocoa using that language through a bridge is generally more difficult that learning it using Objective C.
Finally, much of the recent support for bridged languages was due to "BridgeSupport," a feature was added in Leopard. Even bridges that predate that have been migrating towards, sometimes in such a way that using the bridged language on Tiger and Leopard can have substantial differences. Also, there is currently no bridge support for iPhone, and most bridged languages will not work on it, if that is an issue.
Ultimately, if you are writing a library that is going to be linked into other apps, you need to run on Tiger and Leopard, and you need to access Cocoa only APIs I think you will find using any non-Objective C solution quite difficult.
You can try PyObjC to write Cocoa apps in python, or MacRuby if you are interested in Ruby.
You shouldn't be intimidated by Cocoa's retain/release reference counting. It's much, much easier in practice than GC fans would have you believe. The Cocoa memory management rules are dead simple, they only affect a tiny amount of your code, and even that code can be generated automagically.
Here's the trick. You encapsulate your MM code in accessor methods, and always use accessors. Xcode has built-in scripts to generate the appropriate accessors, or if you need more flexibility there are 3rd-part apps like Accessorizer.
This isn't an intrusive approach - you only need to worry about retaining an object if you're going to need to keep it for later use, and if you're going to do that you'll need an instance variable in which to keep it anyway. And, if you're using KVO and bindings, you'll need to use accessors to make sure the appropriate observer notifications are fired. Basically, if you're using good OOP and Cocoa practices, there's practically no additional thought or effort involved with memory management.
Most folks who have difficulty with Cocoa's "manual" memory management are doing so as a result of misusing it. The most common mistake is to scatter the relevant code all over the place. That means that a missing retain, extra release, etc will be difficult to find.
Try any of the Cocoa bridges listed in here http://www.cocoadev.com/index.pl?CocoaBridges
You can also try F-Script - a smalltalk dialect that is written specifically for MacOSX/Cocoa.
RubyCocoa is getting steadily more impressive, and I've seen lots of successful implementations using it. That is, of course, if Ruby's your cup of tea...
You can always use REALbasic (www.realsoftware.com). Real easy and fun to use, not free though. You can not make dylibs (or dll's) using it, but you can use dylibs and dll's in your code. And you can use cocoa libraries as well
Don't forget that you can use java as well, and i don't mean java-cocoa bridge, i mean actual java.
There's also a package from apple that provides you with access to a couple of osx features as well.
Also to comment on Shem's point, if your targeting osx 10.5 and above, you can take advantage of garbage collection.
If you want lisp syntax then Nu is a lisp implemented on top of Objective-C http://www.programming.nu/
Also, FreePascal can generate native Carbon Apps (in progress working for Coccoa)
Look at Python and wxPython (the wxWidgets in Python).
The wxWidgets have a very elegant App-Doc-View application design pattern that's very, very nice. It's not used enough, IMO. I haven't found any wxPython examples of this App-Doc-View example, so you have to use the C examples to reason out how it would work in Python.
I'd post examples, but I haven't got it all working yet, either.
.NET via Mono mono-project.com
See NObjective (http://code.google.com/p/objcmapper/) bridge to Cocoa. It provides more features than others with less overheads.
I'm looking into Mono too. Objective-C is a little too bizarre for me at this point. Too many years doing C/C++, Java, C#, Perl etc. I suppose. All these seem pretty easy to float between. Not so for Objective-C. Love my Mac but afraid it will take too much precious time to master the language.