Programming Notes
nacho4d avatar

Programming Notes

@nacho4d
Notes on Memory Management in 
Objective-C - FMM(Frequently made mistakes)

To understand memory management is one thing (if it's no THE thing )you will be happy to know if you are or aim to be developer.
Cases like: developing a big project in mobile devices like the iPhone and then you realize you are running out of memory or  writing a simple app that suddenly crashes!
These might take hours of debugging to solve and I remember myself not so long time ago thinking - I wouldn't have this problem is I knew memory management rules well from the beginning -.

Everything remains in the object's retainCount and its ownership. This is what I am reviewing here.

Initializing Objects:
You can initialize an object using a alloc init methods, like:

NSArray *myArray = [[NSArray alloc] initWithObjects:@"Obj0", @"Obj1", @"Obj2", nil];
... do something with myArray
[myArray release];

or you can do it by using class methods or many convenience methods to create the object you want (without using alloc init).


NSArray *myArray = [NSArray arrayWithObjects:@"Obj0", @"Obj1", @"Obj2", nil];
... do something with myArray


So, what is the difference?
When you use alloc/init to create an object you own it. Owning and object or having its ownership implies that you are responsible of releasing it. When using init method the object is initialized and its retainCount is set to 1 and the system won't release it for you.
An object can be owned by one or more objects, implying that each of these owners must release it.

When you use one of many convenience methods like -arrayWithObjects: to create you object, you don't own that object. Why? Initialization might be the same, but the difference is that object will be added to an auto-release pool. Hence when the pool gets drained your object will be released also. (Actually, objects are often released earlier when they are not needed anymore)

That was the super easy part.  Now let's see how to pass an object we created to other objects' property.

Retain, assign or copy?

Consider the following code:
@interface UITextView : UIScrollView{



...
}

@property(nonatomic,assign) id delegate;;
@property(nonatomic,copy) NSString *text; 
@property(nonatomic,retain) UIFont *font;

@property (readwrite, retain) UIView *inputView;  


This is part of UITextView class in iOS SDK. Suppose we have an instance textView.


UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];

First, what everybody knows:


  • Retain: the passed object will be retained (its retainCount will increase generally by 1). Here,  textView will own the objects passed to font and inputView property.

  • Assign: the passed object will not be retained, (This is the default). If you don't set explicitly "retain" or "copy" then "assign" attribute will be assumed.

  • Copy: the passed object will be copied (generally a deep copy) Hence textView will own the object passed through text property. But the passed object and the retained object would be the same. When you have a deep copy it does not matter how you change the object from outside textView, it won't have effect, because it not same object as the one stored by text property. It's a mere copy.

Now we are fine with the theory, consider the following examples:

//A
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[self.view addSubview:textView];
[textView release];
//B
NSString *myText2 = [[NSString alloc] initWithContentsOfFile:@"myTextFile.txt"
encoding:NSUTF8StringEncoding
  error:nil];
textView.text = myText2;
[myText2 release];
//C
textView.text = [[NSString alloc] initWithContentsOfFile:@"myTextFile.txt"
encoding:NSUTF8StringEncoding
  error:nil];
//D 
for (int i = 0; i < 100; i++)
textView.text = [[NSString alloc] initWithContentsOfFile:@"myTextFile.txt"
encoding:NSUTF8StringEncoding
  error:nil];
//E
UIView *keyboard = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 216)];
textView.inputView = keyboard;
[keyboard setBackgroundColor:[UIColor redColor]];

[keyboard release];
//F
textView.inputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 216)];
//G
textView.inputView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 216)] autorelease];
//H
textView.text = [NSString stringWithContentsOfFile:@"myTextFile.txt"
  encoding:NSUTF8StringEncoding
error:nil];
//I
for (int i = 0; i < 100; i++)
textView.text = [NSString stringWithContentsOfFile:@"myTextFile.txt"
  encoding:NSUTF8StringEncoding
error:nil];

//J
MyDelegate *myDelegate = [[MyDelegate alloc] initWithSomething];
textView.delegate = myDelegate;
[myDelegate release];
//K
MyDelegate *myDelegate = [[MyDelegate alloc] initWithSomething];
textView.delegate = myDelegate;

//L
textView.delegate =  [[MyDelegate alloc] initWithSomething];


Some of these are very silly, a couple of them is just to show memory leaks in Instruments, but I see very often people write code like this in some programming boards and they are very illustrative.

A is just the initialization of our instance. This is not about properties.

B, C, D are samples regarding "copy" property attribute. This is the case of text property.

B is correct. Allocate and initialize myText2 (retainCount is 1), is then passed through text property then is copied, and since needed no more it's released. No leaks, we are fine.

C is wrong. You might be tempted to shorten your B code like C but this will cause memory leaks.
Reason: When you allocate and initialize your object it will have retainCount 1 and right after that it is passed through text property then is copied and you don't have a reference to release!.  This will be be more clearer in D.

D is just for illustrative purposes, you surely never want to do this. I did this just to make the leak very obvious in Instruments.
This is what I got in Instruments: pretty bad huh? Got 5 MB leaking (since my file size is 5KB)

Fig 1: Instruments showing leaked memory.


E and F are samples regarding "retain" property attribute. This is the case of inputView property.

E is correct, is basically like B, just this time keyboard is not copied, is the same object with it's retainCount increased. The big difference with copy is that if you change keyboard after you pass it to  textView.inputView it will do have effect on textView 's input view because is the same object.

F is wrong, is very similar to C, just this time the object you created using alloc and initWithFrame: methods is the same as the one stored through inputView property. Hence you have a reference and could solve this leak later (by doing [textView.inputView release];) but it will be ugly to my taste.

G is correct, this is what you want if you want to shorten E or correct F. I would use E rather than G.

H and I are samples regarding retain/copy but when using not owned objects. (object that will be autoreleased by an auto-release pool)

H is fine. In C, the bug was that object created just before passing it thought text property would not be released, but using the convenience method: -stringWithContentsOfFile:encoding:error: instead of initWithContentsOfFile:encoding:error: the problem is solved.
Why? when using those convenience methods the object returned is automatically polled in the most recent autorelease pool.
How do I recognize a convenience method? the rule is simple: if the word "init" is present in the method name (signature) then you will have the ownership of the object, meaning that you have to release it by yourself. Otherwise, is a convenience method, you will not have the ownership of the object because it will be added to an autorelease pool. You don't need to release it.

I is just to show that using this approach won't leak memory as D
This is what I got in Instruments:

Fig 2: Instruments showing allocation of first 100 text objects (starting the app).
Fig 3: Instruments showing released objects (app is already started).


Since I am allocating 100 times the same object then Allocations instrument shows a big amount of memory allocated at the beginning (shown in Fig 2). But since that memory is owned by the system, is drained when is not needed anymore (when the app finished loading), as shown in Fig 3

J,K and L are to show "assign" property attribute.
Assign behaves like retain in the sense is the same object (not a copy) is stored. The difference is that the object passed is not retained.

J is not wrong from the memory management point of view, but is not what you want because textView property will not retain myDelegate object. Hence releasing myDelegate right after setting the delegate through inputView property is meaningless, because the object will be deallocated.


K is what you want to do instead of J. This is correct.

L is the shortened version of K, since delegate property attribute is assign, textView will not retain myDelegate. Hence allocating and initializing and object and passing it is not a problem like in C or F.

So why assign this useful? it depends on your needs actually. The most famous usage is a delegate.
If object X retain an object Y that retains X, both objects will never be released, this is also a memory problem. you create objects that cannot be released. In this case assign becomes useful.

With this I've finished this quite long post. I hope it helped a little bit someone.
Actually I wanted to write also about how to write your own classes with properties, how to properly initialize and release them, but this post is too long already. A new post is better ;)



TODO:
Designing/Making/Using your own classes with properties

in UIViewController/ NSWindowController
in loadView/viewDidLoad
address problems like
NSString *string = [[NSString alloc] init];
string = [otherString stringByAppendingString:@"asd"];

NSString *string = [NSString string];
string = [otherString stringByAppendingString:@"asd"];

NSString *string = [otherString stringByAppendingString:@"asd"];

view didUnload:
self. retainProperty = nil;
[retainProperty release];
assignProperty = nil

in dealloc
[retainProperty release];
assignProperty = nil;
[copyProperty release];



Implementing Objective-C Delegation in C++

Sometimes I wan't to implement things like I would do it in Objective-C when working in C++. But in C++ there is no such a thing like delegation. (At least not with that name)
These are just a few notes on how to implement a delegate or delegation in C++. Is not complicated at all the only thing you need is to find the equivalents for Protocols, Delegates, in C++.

Note1: There are no protocols in C++ but you can use interfaces and multi-inheritance to accomplish this.
For example in Objective-C, let's suppose you write something like this:


@protocol UITableViewDataSource;
@interface UITableView : UIScrollView{
@private
    id<UITableViewDataSource>   _dataSource;
}
@end

and


@protocol UITableViewDataSource;
@required
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section;
@end

Then (assuming you have the same class names) in C++ you will write something like this:

class UITableViewDataSource;
class UITableView : public UIScrollView {
    UITableViewDataSource *_dataSource;
};

class UITableViewDataSource{
    virtual NSInteger tableViewNumberOfRowsInSection(UITableView* tableView, NSInteger section);
}

So, how you implement your protocol?
In Objective-C:


@class MyDataSource <UITableViewDataSource> {
    NSArray *array;
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section;
@end

@implementation MyDataSource
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section{
    return [array count];
}
@end


In C++ (Assuming there is a NSArray class in c++)


class MyDataSource : public UITableViewDataSource {
    NSArray *array;
    virtual NSInteger tableViewNumberOfRowsInSection(UITableView* tableView, NSInteger section);
};


NSInteger MyDataSource::tableViewNumberOfRowsInSection(UITableView* tableView, NSInteger section){
    return array->count();
}


In C++ multi-inheritance is allowed so could have a controller class that is a controller and also implements UITableViewDataSource interface. (Or in Objective-C words: conforms to UITableViewDataSource protocol)

If in Objective-C you have:


@class TableViewController : UIViewController < UITableViewDataSource > { ...


in C++ you will have:


class TableViewController : public UIViewController, public UITableViewDataSource { ...


Multi-inheritance + interfaces plays quite the same role as protocols.

Note2: There are no selectors in C++ but you can pass a method as a pointer. This is useful when you want  to set a method to be called by other object.
TODO: add samples: for [object performSelector:@selector(aMethod:) withObject:argument afterDelay:0.0];
TODO: add samples for method pointers in C++


Note3: C++ does not bring any kind of concurrency APIs so you will have get your own. Boost thread, OpenCL, CUDA, OpenMP. I think OpenMP is the simplest option here. Most compilers implement it and just with a few lines of #pragma you are done. But if you get really serious and need not only multithreading but also GPU/CPU power then OpenCL is the best option,  OpenCL is a young but powerful bunch of APIs for multi GPU/CPU programming, version 1.1 was just approved by Khronos group last month and with this new update we are able to run c++ code in it. The bad thing is we have to wait until Apple or your hardware vendor implements since OpenCL is just a specification.

TODO:add some links to OpenMP and Boost examples
TODO: add some links to OpenCL

Using PointGrey Research Cameras with OpenCV 2.1.1 in Macs

Point Grey Research makes really good industrial cameras that are suitable for many kinds of image processing researches. The big con for me is that they don't or plan to offer support for Mac OS X. Luckily with the new Quick Time libraries (QTKit.framework) we can use those cameras.

There are two alternatives, you can become a native citizen and use Objective-C, Cocoa and QTKit directly or you can use OpenCV (a C/C++ image processing library) that uses QTKit internally.

OpenCV is an open source project for image processing, computer vision, machine learning and many other areas, is very useful and developed by a very active group!. Since version 2.1 OpenCV uses QTKit.framework to get frames into images (IplImages).

This is just a couple of notes you should take in count when using this unsupported cameras, you have two options:

Option 1: Modify your program

When using PGR cams in macs you MUST set a width and height to the Video Capturer like this:

using namespace cv;
int main(int, char**)
{
 VideoCapture cap = VideoCapture(1);
 cap.set(CV_CAP_PROP_FRAME_WIDTH, 320); //LINE ADDED
 cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240); //LINE ADDED
 if(!cap.isOpened()) return -1;

 namedWindow("edges",1);
 for(;;)
 {
  Mat frame;
  cap >> frame;
  imshow("edges", frame);
  if(waitKey(30) >= 0) break;
 }
 return 0;
}

If you don't set a width and height then the window will never appear. No errors, nothing happens. Probably you will be debugging for hours or end up by using another camera.
If don't want to modify every single program you have, you simply modify OpenCV, is less than 10 lines including building and installing. These is the best part of open software stuff!

Option 2: Modify OpenCV

Find the file to modify

Locate file "cap_qtkit.mm" and open it. It should be in "opencv/modules/highgui/src/" or just do a search.
Find startCaptureDevice() method implementation, it should look something like this:

int CvCaptureCAM::startCaptureDevice(int cameraNum){
  ...
}

Modify the file

Inside startCaptureDevice() method you will find these lines:

NSDictionary *pixelBufferOptions ;
if (width > 0 && height > 0) {

We are gonna modify the code just before those line as in the picture:



Here is the code:

//start of modification
if (width == 0 && height == 0 && [[device description] isEqualToString:@"Camera"]) {
 width = 640; height = 480;
}
//end of modification

Now just built and compile OpenCV and your are done!
(You can refer these instructions if you don't know how, also make sure you have your cmake updated)

Explanation

PGR cams are not made to work with macs, but happily they conform to some protocols (I believe one of them is ieee1394) so they actually do!. They problem seems to be in some of them default parameters
So when we are just about to initialize a PGR cam, we simply set good defaults.

How to recognize a PGR cam? I have realized that when printing all devices descriptions PGR cameras shows a string Camera.
So printing all devices in a MacBook with a PGR cam will show something like this:

"Built-in Input",
"Built-in Microphone"
"Built-in iSight"
"Camera"

That is why we check for a device whose description is Camera and its width and height hasn't been set.

More on PGR cams and their pixel formats:

I have tested with QTKit.framework and Objective-C and only a reduced group of pixel format seems to  work with my PGR cam (Grasshopper) . I said seem to work because I didn't check the pixels, I just used a QTCaptureView object to see the results.

kCVPixelFormatType_32ARGB
kCVPixelFormatType_32BGRA
kCVPixelFormatType_32ABGR
kCVPixelFormatType_32RGBA
kCVPixelFormatType_64ARGB

Only those worked for me, but I didn't test all of them (they are too many!) Even though this is more than necessary to work with raw pixels.

References

Installing and Using OpenCV 2.1.1 in Snow Leopard


Update 2011/07/26:

It is easier to install homebrew and then install opencv using it:
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"
$ brew install opencv
And you are done!
Now add the headers to your project as shown in step 3 and 4 :)


I use OpenCV very often for my projects. I like it because it has some interesting and very useful implementations. What I don't like is kind of messy and docs update are slow. Specially documentation for Macs is slow!

So I just followed some instructions from here, read some other info from here and realized opencv's new structure by looking at the installed files.

This post shows how to run the sample code I got from here

Step 1: Get and Configure OpenCV 2.1.1:


In the Terminal,
$ svn co https://code.ros.org/svn/opencv/trunk/opencv
$ cd opencv
$ mkdir build
$ cd build
$ cmake ..
Optionally you can configure some flags using cmake configure tool

Step 2: Build and Install OpenCV 2.1.1:

$ make -j8
$ sudo make install

And we are done!

Step 3: Create a Xcode Project:

(I am using Xcode 3.2.2)

In Xcode, create a Standard C++ project by doing: File>New Project...
Select "Application" from MacOS X left menu and "Command line tool" type: "C++ stdc".

Step 4: Use OpenCV 2.1.1


Add OpenCV 2.1.1 Headers Path

  • Select Project>Edit Project Settings...
  • Set Configuration to "All Configurations"
  • In the "Architectures" section, double-click "Valid Architectures" and remove all PPC architectures
  • In "Search Paths" section set "Header Search Paths" to /usr/local/include/
    (What we are doing is add the path where opencv's headers folder is)
  • Close the Project Info window


Add OpenCV 2.1.1 Libraries (Dylibs)

  • Select Project -> New Group and create a group called OpenCV Frameworks
  • With the new group selected, select Project -> Add to Project…
  • Press the "/" key to get the Go to the folder prompt
  • Enter /usr/local/lib
  • Select the libraries needed or all of them:
    libopencv_calib3d.2.1.1.dylib
    libopencv_contrib.2.1.1.dylib
    libopencv_core.2.1.1.dylib
    libopencv_features2d.2.1.1.dylib
    libopencv_highgui.2.1.1.dylib
    libopencv_imgproc.2.1.1.dylib
    libopencv_legacy.2.1.1.dylib
    libopencv_ml.2.1.1.dylib
    libopencv_objdetect.2.1.1.dylib
    libopencv_video.2.1.1.dylib
    


Uncheck "Copy resources" when  asked, importing a reference is enough.

Include OpenCV 2.1.1 headers in your code:


In prior versions of OpenCV we would have written:
#include "cv.h"; or depending on your header search path #include "opencv/cv.h"; but in OpenCV2.1.1 file structure is changed, so including headers like that will cause at least some warnings. (Because those headers are deprecated) So let's do it the new way:

#include "opencv2/imgproc/imgproc.hpp" //for image processing
#include "opencv2/highgui/highgui.hpp" //for GUI

You will need to include more headers if you are doing other stuff like machine learning, etc. If you are not sure what headers you should include just check directory:
/usr/local/include/opencv2/
You will realize that OpenCV 2.1.1 is now divided in modules!



Now build and Run and you should have your program running ;)
You can download my sample project from here.

I hope it helps ;)

Installing ARToolKit with VRML support in Windows (VS 2005) was such a pain in the ... !!!
But I think I finally got it correct.
I followed instructions from here
http://www.hitlabnz.org/forum/showthread.php?t=287
and Instructions in Japanese can be found here:
知り合いは 自分のブログで翻訳してくれたので 日本語がいいと思う方はこちら http://ameblo.jp/hidelab/entry-10154213023.html

And If you don't want to do all this tedious thing you just can download my project.
(I did exactly as the above link.)
Download from rapid share (MD5: 55FDF958B36BE124490068F99CED3EAB)



I don't know if this is going to work in Visual Studio 2008 but At least here we have much better chances than then VS2003 project

なちょは、私の王子さま

This work is licensed under BSD Zero Clause License | nacho4d ®