Showing posts with label GNUstep. Show all posts
Showing posts with label GNUstep. Show all posts

Monday, December 22, 2008

Cocoa Memory Management

It becomes evident, thanks to the mass centralisation of the neverending september effect that is stackoverflow, that despite the large number of electrons expended on documenting the retain/release/autorelease reference counting mechanism for managing memory in Cocoa, Cocoa Touch, UIKit, AppKit, Foundation, GNUstep, Cocotron and Objective-C code, very few people are reading that. My purpose in this post is not to re-state anything which has already been said. My purpose is to aggregate information I've found on the topic of managing memory in Cocoa, so I can quote this post in answers to questions like these.

In fact, I've already answered this question myself, as How does reference counting work? As mentioned in the FAQ, I actually answered the question "how do I manage object lifecycles in (Cocoa|GNUstep|Cocotron)"? It's actually a very violently distilled discussion, so it's definitely worth checking out the references (sorry) below.

Apple have a very good, and complete, Memory Management Programming Guide for Cocoa. They also provide a Garbage Collection Programming Guide; remember that Objective-C garbage collection is opt-in on 10.5 and above (and unavailable on iPhone OS or earlier versions of Mac OS X). GNUsteppers reading along should remember that the garbage collector available with the GNU objc runtime is entirely unlike the collector documented in Apple's guide. GNUstep documentation contains a similar guide to memory management, as well as going into more depth about memory allocation and zones. Apple will also tell you how objects in NIBs are managed.

The article which gave me my personal eureka moment was Hold Me, Use Me, Free Me by Don Yacktman. Stepwise has another article, very simple rules for memory management in Cocoa by mmalc, which is a good introduction though with one caveat. While the table of memory management methods at the top of the article are indeed accurate, they might give you the impression that keeping track of the retain count is what you're supposed to be doing. It's not :). What you're supposed to be doing is balancing your own use of the methods for any given object, as described in rules 1 and 2 of "Retention Count rules" just below that table.

James Duncan Davidson's book "Learning Cocoa with Objective-C" has not been updated in donkey's years, but its section on memory management is quite good, especially the diagrams and the "rules of thumb" summary. Luckily, that section on memory management is the free sample on O'Reilly's website.

If reading the theoretical stuff is all a bit too dry, the Mac Developer Network have a rather comprehensive memory management training video which is $9.99 for non-MDN members and free for paid-up members.

Finally, Chris Hanson has written a good article on interactions between Cocoa memory management and objc-exceptions; if you're using exceptions this is a good discussion of the caveats you might meet.

Sunday, December 21, 2008

better security, not always more security

Today's investigative investigations have taken me to the land of Distributed Objects, that somewhat famous implementation of the Proxy pattern used for intra-process, inter-process and inter-machine communication in Cocoa. Well, by people who measure whether it's a performance hog, rather than those who quote it; as a hint, it was indeed a significant overhead when your CPU was a 25MHz 68030 and your network link a 10BASE-2 coaxial wire. These days we can spend around those problems freely.

Specifically, I wondered whether I should add discussion of the authentication capabilities in PDO to the FAQ entry. Not that it's frequently asked - indeed, it's a NAQ - but because getting mentions of security into a Usenet FAQ is likely to cause newbies to be thinking about security, which is possibly a good thing (for the world, not so much my uniquely employable attributes). But I decided no, though the subject is interesting, it's not because of the technicality, but the philosophy.

Distributed Objects works by sending NSPortMessage messages over NSConnection connections. The connections and message-passing bumph are peer-to-peer, but DO adds some client-server distinction by having servers register their vended connections with name servers and clients look up the interesting vendors in said name servers. By default, anything goes; all connections are honoured and all clients serviced. There are two security features (both implemented as delegate methods) baked into DO, though. The most interesting of the two is the authentication.

The reason that the authentication feature is interesting is that it's implemented in such a way as to make non-security-conscious developers question the security. The end sending the NSPortMessage includes some data based on the constituent parts of the message, and the end receiving the message decides whether to accept it based on knowledge of the constituents and of the data. On the face of it, this looks like shared-secret encryption, with the shared secret being the algorithm used to hash the port message. It also appears to have added no security at all, because the message is still sent in plain text. In fact, what this gives us is more subtle.

All that we know is that given the source information and the sender's authentication data, the receiver gets to decide whether to accept the sender's message. We don't necessarily know the way that the receiver gets to that decision. Perhaps it hashes the information using the same algorithm as the sender. Perhaps it always returns YES. Perhaps it always expects the authentication data to be 42. On the other hand, perhaps it knows the public key of the sender, and the authentication data is a signature derived from the content and the sender's private key. Or perhaps the "authentication data" isn't used at all, but the source material gives the server a chance to filter malicious requests.

Now all of that is very interesting. We've gone from a system which looked to be based on a shared secret, to one which appears to be based on whichever authentication approach we decide is appropriate for the task at hand. Given a presumed-safe inter-process link, we don't need to be as heavyweight about security as to require PKI; whereas if the authentication were provided by a secure tunnel such as DO-over-SSL, we'd have no choice but to accept the cost of the PKI infrastructure. Given the expectation of a safe server talking to hostile clients, the server (or, with some amount of custom codery, a DO proxy server) can even sanitise or reject malicious messages. Or it could both filter requests based on authentication and on content. The DO authentication mechanism has baked in absolutely zero policy about how authentication should proceed, by letting us answer the simple question: should this message be processed? Yes or no? Choose an approach to answering this question based not on what you currently believe could never be circumvented, but on what you currently believe is sufficient for the environment in which your DO processes will live. If a shared secret is sufficient and adds little overhead, then do that, rather than 4096-bit asymmetric encryption.

By the way, the second security feature in DO is the ability to drop a connection when it's requested. This allows a DO server to survive a DoS, even from a concerted multitude of otherwise permissible clients.

Tuesday, June 24, 2008

Objective-C NAQs

Never-Asked Questions :-)

In Code Complete 2 §6.5, Steve McConnell presents a list of class-related design issues that "vary significantly depending on the language". So why don't we look at them for Objective-C? Especially as I can't find anyone else who's done so based on a couple of Google searches… N.B. as ever, I'm really considering Cocoa + Objective-C here, as the language itself doesn't provide enough policy for many of the issues to have an answer (only method resolution and the existence of isa are defined by the runtime and the compiler - ignoring details like static string instances, @protocol and so on).

Behaviour of overridden constructors and destructors in an inheritance tree. Constructors are simple. If you can initialise an object, return it. If you can't, return nil. The -[NSObject init] method is documented as simply returning self.

For destructors, we have to split the discussion into twain; half for garbage collection and half for not. In the world of the Apple GC, destruction is best done automatically, but if you need to do any explicit cleanup then your object implements -finalize. The two rules are that you don't know whether other objects have already been finalized or not, and that you must not resurrect your object. In the world of non-GC, an object is sent -dealloc when it has been released enough times not to stick around. The object should then free any memory claimed during its lifetime, and finally call [super dealloc]. Note that this means objects which use the voodoo cohesion of "OK, I'll clean up all my resources in -dealloc" probably aren't going to work too well if the garbage collection switch is flipped.

Behaviour of constructors and destructors under exception-handling conditions. Exceptions are a rarity in Cocoa code (we didn't have language-level exceptions for the first decade, and then there was a feeling that they're too expensive; C++ programmers like the Leopard 64-bit runtime because ObjC exceptions and C++ exceptions are compatible but that's not the case in the NeXT runtime) but obviously a constructor is an atomic operation. You can either initialise an object or you can't; there's no half-object. Therefore if an -init… method catches, the thing to do is unwind the initialisation and return nil. The only thing I can think to say for having exceptions around destruction time is "don't", but maybe a commenter will have better ideas.

Importance of default constructors. All classes implement -init, except those that don't ;-). Usually if there's a parameterised initialiser (-initWithFoo:) then that will be the designated initialiser, and -init will just return [self initWithFoo: someReasonableDefaultValueForFoo];. If there's no reasonable default, then there's no -init. And sometimes you just shouldn't use -init, for instance NSNull or NSWorkspace.

Time at which a destructor or finalizer is called. See How does reference counting work? for a discussion of when objects get dealloced. In the garbage-collected world, an object will be finalized at some time after it is no longer reachable in the object graph. When that is exactly really depends on the implementation of the collector and shouldn't be relied on. Temporal cohesion ("B happens after A, therefore A has been done before B") is usually bad.

Wisdom of overriding the language's built-in operators, including assignment and equality. This is such a brain-damaged idea that the language doesn't even let you do it.

How memory is handled as objects are created and destroyed or as they are declared and go out of scope. How does reference counting work? How do I start using the garbage collector?

Thursday, June 12, 2008

WWDC day three

Today was not quite a full day, so I managed to spend about an hour or so milling around Yerba Buena park, doing a little gift shopping and generally existing outside of the Mascarpone centre. Also put in another update to the c.l.o-c FAQ (though I didn't update the date! oops…) to better discuss retain/release memory management. There are still situations (GNUstep, Cocotron, and some particular OS X environments) where garbage collection is either unavailable or unsuitable, and it turns out that a lot of questions on either the group or cocoa-dev recently have been about the memory management system.

In the evening, after dinner at Chevy's with the u.c.s.m guys (and yet more discussion of the Sophos feature set), checked in to the Apple Design Awards for the first 30 mins or so. All of the winners (and runners-up) I saw were worthy applications, although it was interesting to note that while most of the "productivity" app winners were from small shops, both of the games (runner-up was Command and Conquer 3, winner was Guitar Hero 3) were from large studios, ports of Windows/console games and in existing long-running series. They're both great games, too, of course. Ian was, of course, rooting for Delicious Library 2, and sadly disappointed ;-).

This was all followed by the AFP548 beer bash over at Thirsty Bear. Yet more "oh, you're from Sophos? Yeah, let me say this one thing…", which I really enjoy because if something's either good or bad enough to be the subject of a beer-fuelled rant in a party, I should probably hear about it. Also submitted a couple of entries to Peter's "Leopard bug Venn diagram" contest; I'm not sure I could do a better job of describing the situation than that but for those who were there, I came up with: \Omega = "Closed/Duplicate" and \Omega = "NeXTSTEP 7.0".

Tuesday, June 10, 2008

WWDC - day one

The WWDC keynote is always an odd event to attend. It's put on for the benefit of the investors and the media, with the developers being invited purely to act as braying masses expressing their adulation for His Steveness. It's rare for any technical content to make it into the session, except in unavoidable cases such as the 2005 keynote. The focus of that was the Intel transition, so by necessity there had to be some technical justification of the switch.

With this in mind, it's not hard to see that the keynote can be a somewhat dull affair. Obviously as both an Apple customer and member of the "economic ecosystem" of the Mac, it's always good to be as informed as possible of the company's position and direction. That said, yesterday's keynote (no wi-fi in this hotel, so a late post) contained less of interest to me than usual.

As I mentioned I'm financially dependent on Apple (in an indirect sense of course; I'm paid to write Mac software for Sophos, therefore no Mac = no job at Sophos), though as I'm not an indie dev I have a bit more of a comfort buffer than many people. The enterprise iPhone video Steve showed was basically a backslap in front of the shareholders; look, there are people who really do use this stuff! Then the laundry list of every developer who's downloaded the SDK and managed to get something to compile; interesting to see the wealth of different domains into which the iPhone is entering, but seriously. Two demos, three tops. Not all four thousand of the known apps. Good to see TEH CHEAP being applied to the 3G iPhone, though; I may have to
have a discussion with Orange about a PAC when that's available.

Which left Mobile Me. This is actually a pretty cool reboot of iTools^W.Mac, OK it looks like there might be no more iCards but on the other hand the Mobile Me syncing is really beneficial. I can see that becoming more of a cash cow for Apple, though mainly because they opened it up to the PC; people who have an iPod and Windoze could buy MM to synchronise their contacts, mail and so on, as well as getting webmail access (and webmail access which doesn't suck balls as much as
Exchange's OWA, may I add). That then might make them more amenable to the Halo Effect and the purchase of a Mac down the line.

The rest of the day was interesting but obviously undisclosable, except for the evening I spent in a couple of bars down the financial district (the Golden%Braeburn event at 111 Minna, where I went with Steffi from BNR and a couple of Cocotron committers; then Dave's bar where I met Nigel and most of Apple UK). Conversation ranged from Sophos feature requests to the drinkability of American IPAs; all good stuff!

Wednesday, June 04, 2008

Little hack to help with testing

Want the ability to switch in different test drivers, mock objects, or other test-specific behaviour? Here's a pattern I came up with (about a year ago) to do that in a GNUstep test tool, which can readily be used in Cocoa:


NSString *driverClassName = [[NSUserDefaults standardUserDefaults] stringForKey: @"Class"];
Class driverClass = NSClassFromString(driverClassName);
id myDriver = [[driverClass alloc] init];

With a healthy dose of no, seriously, don't do this in production code, you now have the ability to specify your test driver on the command-line like this:


$ ./myTestingTool -Class GLTestDriver

This uses the oft-neglected behaviour of NSUserDefaults, in which it parses the executable's command-line arguments to create a defaults domain, higher in priority than even the user's preferences file. You can use that behaviour in a graphical app too, where it comes in handy when working in Xcode. It then uses a combination of the runtime's duck typing and introspection capabilities to create an instance of the appropriate class.

Friday, March 14, 2008

Nice things about ObjC

Title linkies to a post by an F-Script guy (the F-Script guy? I'm not sure, I don't really follow F-Script development) about nice things he likes about the Objective-C language. Remembering that he wrote a Smalltalk scripting environment for Cocoa, some of the list is fairly unsurprising, much is made of the dynamic runtime, multiple-level dispatch and so on. I think the article is mainly bang on, though I do disagree with the author in a few places. The next paragraph is not one of those places.


Classes are objects. ++ This is the coolest thing ever about proper object-oriented languages, and one of my strongest arguments for design patterns are not language independent. Do patterns such as Prototype need to exist in ObjC code, when the Factory Method +new will give you an unconfigured typical instance?


Dynamic typing... Optional static typing. This is one of those slippery slopes where both edges are sharp enough to give you the rope required to shoot yourself in the foot. Duck typing (i.e. if an object looks like a duck, and quacks like a duck...) is useful in some cases and damned annoying in others. To avoid runtime exceptions with duck typing you either have to [i]mentally assert correctness in your code, [ii]perform all the runtime introspection needed to ensure your messages will be handled, or [iii]eschew the duck type completely and downcast to either an instance of a class or a conformant of a protocol (or both; you could do something like GLModelObject <NSCoding> * if you really felt like it). Another issue with the ObjC implementation of duck typing is that it doesn't always work as you'd think. When it does work, it's very powerful - when it doesn't, you probably won't find out until runtime, and could be spending a long while working out what happened.


Categories. No, afraid not. Nice idea, badly implemented. The point of categories is to let you decorate a class with additional functionality by adding methods - currently not ivars - in additional code objects, not all of which need be present at launch. This lets you work around the visibility contract of the class (can't see an @private ivar? Just chuck an instance method in!), though in fairness so does KVC. But perhaps the worst crime a category can commit is killing someone else's category. Or overwriting an "undecorated" method.


I still love Objective-C, mainly because I love Cocoa and GNUstep and making code that works like them, it's definitely powerful and fun too. But it's not without its rough edges and sharp spiky bits.

Wednesday, January 23, 2008

How to solve every problem in Cocoa

Yes, really, every problem. Don't think of Cocoa as "simple things simple, complex things possible" (actually, was it Cocoapenextstepsody or Perl who started with that tagline? Or someone else? I digress) but "simple things simple, complex things simple but you're looking at it wrong". With Objective-C 2.0 (particularly properties), Core Data, Cocoa Bindings and Cocoa Scripting, almost every "it doesn't work" moment comes down to getting something wrong with KVC or with KVO - either observing the wrong key, or typoing a method name such that you aren't KVC-compliant for a key you need to be, getting validation wrong or unexpectedly going down the -setNilValueForKey: path. So do yourself a favour:


#define GLInstanceMethodEntryLog(format, ...) NSLog(@"-[%@(%p) %@] entry: %@", NSStringFromClass([self class]), self, NSStringFromSelector(_cmd), [NSString stringWithFormat: format, ##__VA_ARGS__])

Now because all of the retain count bugs disappeared when you turned the garbage collector on, the remaining issues are with that bit of code the PHBs are paying for ;-)

Saturday, December 08, 2007

Objective-C Design Patterns

Certain events at work have turned me into a bit of a design patterns geek of late, and as such I stumbled across this DDJ article from 1997 (the title of this post is the link). According to del.icio.us not many other people have stumbled across it, but it's a great article. The code listing links seem to 404 even though the listings are at the bottom of page 1 of the article.


Something very important can be learned from this article, which is at best covered tangentially in the GoF book: Design patterns are not language-independent. Calling the C++ and Objective-C ways of writing code "pattern idioms" ignores the point that actually, the code you come up with is more important than the design (customers don't typically want to pay the same cash for your UML diagrams that they do for your executables), and gasp different languages require different code! Different patterns can be used in ObjC and Smalltalk than in C++, and different patterns again in object-oriented Perl. Different patterns will be appropriate for working with Foundation than with the NeXTSTEP (pre 4.0) foundation kit or with ICPak101. Designing your solution independent of the language and framework you're going to use will get you a solution, but will not necessarily produce the easiest solution to maintain, the most efficient solution or one that makes any sense to an expert in the realm of that language and framework.

Tuesday, December 04, 2007

FSF membership

I am now an associate member of the FSF. This is a good way to support Free Software development (including GNUstep, and you don't even need to be able to code :-). I've added a referral link to the sidebar - I don't get a kickback obviously, although I do get gifts if enough people are referred by me, and it helps the FSF to track where donors are getting their information from. If you use Free Software, you might consider donating some cash - especially now that the dollar's so crap ;-).

Saturday, August 18, 2007

It's update o'clock

In other words, it's "Graham remembers that someone needs to write the interwebs, too" time. The main reason I haven't written in a while is that I'm enjoying the new job, so it's satiating my hacking desires. No hacking projects = nothing to talk about. I can't really talk about the work stuff, either; this is unfortunate because I did some really cool KVC-cheating in a prototype app I wrote, and it'd be a good article to describe that.


I've more or less dropped off the GNUstep radar recently. I still need to talk to the employers' legal eagles in order to update my FSF copyright assignment, and then find something to hack on. Currently I only have a Mac OS X machine so I'd probably switch to some app-level stuff. I have half a plan in my mind for a SOPE app, but despite reading all the documentation I still haven't worked out how to get started :-|. The code isn't too much of a problem, I've used WebObejcts before, but WebObjects has a 'hit this button to build and run your WebObjects code' button, and there's no description AFAICT for SOPE of what to put in the GNUmakefile to get built and running SOPE code, even whether you're supposed to provide your own main() or anything. Hmmm...I wonder if there's a sample project around...

Monday, June 11, 2007

Miniwindows

Maybe it's just me who gets annoyed by teeny-tiny miniaturised views which are completely illegible. Even so, I've just uploaded an article I wrote on Miniwindows which can be used in any OpenStep implementation such as Cocoa or GNUstep. It's based on the Hillegass TypingTutor example, but doesn't really use any code from that and isn't (I hope) otherwise reliant on that context, so it should be possible to see what's going on even if you haven't read Hillegass. Which you should ;-)

Thursday, March 15, 2007

Summer of code

GNUstep has been approved for this year's Google Summer of Code. The title link goes to the GNUstep wiki page outlining possible projects, but I'm sure that if a student had another idea you'd be welcome to talk about it on the gnustep-discuss mailing list, and probably get a mentor!

Monday, February 26, 2007

FOSDEM / GNUstep photos

Just came in on #gnustep. Many photos of the GNUstep booth, dev room and of course the famous GNUstep dinner.

Sunday, February 25, 2007

Apres ca, le FOSDEM

It appears that I'm sat in Terminal B of L'Aeroporte Nationale de Bruxelles, waiting for my flight to board. While there are wirelesses around, the ones to which I can connect seem not to be offering much in the way of DHCP so this update will come in later than it was written (which was at 13:35), as I will probably post it while I'm on the bus between Heathrow and Oxford. [Update: actually not until I got home]



Irrelevancies such as that aside, I had a great FOSDEM! In fact, a great half-FOSDEM, as I did my tourism today. I met a load of people (of which more below), went to some inspiring talks and discussed many exciting and interesting projects (in multiple languages - I spoke to one person in English, Dutch and French sometimes in the same sentence). It was a good exercise to see who wasn't present as much as who was - for instance RedHat didn't have an official presence although the Fedora Project had a booth (next to the CentOS one ;-), similarly Novell (one of the big sponsors) was absent but the OpenSUSE project had Yet Another Small Table. Sun were conspicuously present in that the OpenSolaris and OpenJDK table was being manned seemingly by Sun's salespeople rather than user group members...although maybe that's just my interpretation.



The overriding feeling I got was that the conference was running on l'espirit d'anarchie and that the resulting adrenaline and enthusiasm drove the conference on. The keynote speeches were really the only regimented aspect of FOSDEM - a necessity given the size of the auditorium and that was packed to the rafters with FLOSSers. I didn't go to the final keynote on open-sourcing Java as I was manning the GNUstep booth, but learned a lot on software patents and Free Software and Jim Gettys' description of the technical challenges in creating OLPC was very insightful.



So, GNUstep. GNUstep, GNUstep, Etoile [I'll add the accents in in a later update...this keyboard doesn't have dead keys :-(]. For a start it was great to meet all the other GNUsteppers, and have some good discussions and debates (as well as some good moule frites and Kwak beer). For anyone who doubts that GNUstep is still alive, the dev room at FOSDEM is one place to allay such suspicions with many developers, designers, users and supporters presenting their ideas to each other, asking each other questions and generally contributing to the GNUstep camaraderie. Even an improptu troll by Miguel de Icaza at the GNUstep booth wasn't enough to make us all throw Project Center away and buy a book on C# ;-). Presentations on GNUstep-make v2 (which I've described here before...), the Cairo graphics back-end (which I don't think Fred Kiefer was expecting to present, but made a very fine job of it anyway) and third-party use of GNUstep were all very useful and well-received...I expect today's presentations were too but I didn't get to go to them :-(. [Instead, I was significantly underwhelmed by the sight of the Mannekin Pis.]

Tuesday, February 20, 2007

Fairly cool update to GNUstep

GNUstep-make now supports arbitrary(-ish) filesystem layouts. While the default is still the /usr/GNUstep layout with the various domains, one of the bundled alternatives is to put everything in FHS-compliant locations. Once that hits a release (which I believe will be called gnustep-make 2.0), that should make newbie users and distributors much more comfortable with GNUstep. I also provided a NeXT-ish layout which doesn't clone the NeXT directory hierarchy, but rather mimics it sensitively.

My work laptop just earned itself a reinstall (I'd been uncomfortable with CentOS for a while, but the facts that hotplug isn't configured properly and every time I 'yum update' I have to fix a handful of drivers drove me over the edge), so when I re-create my GNUstep installation I'll do it with the new-style make. I'm currently wavering on the side of installing Midnight BSD, but I might wimp out and dual-boot Ubuntu ;-)