Blocks, closures on stack and heap

Blocks on the Stack

While reading through Apple’s open source code (headers) I came across queue.h and stumbled over the following warning:

/*!
 *
 [...]
 *
 * dispatch_block_t block;
 *
 * if (x) {
 *     block = ^{ printf("true\n"); };
 * } else {
 *     block = ^{ printf("false\n"); };
 * }
 * block(); // unsafe!!!
 *
 * What is happening behind the scenes:
 *
 * if (x) {
 *     struct Block __tmp_1 = ...; // setup details
 *     block = &__tmp_1;
 * } else {
 *     struct Block __tmp_2 = ...; // setup details
 *     block = &__tmp_2;
 * }
 *
 * As the example demonstrates, the address of a stack variable is escaping the
 * scope in which it is allocated. That is a classic C bug.
 */

I got curious and so I followed the rabbit down the rabbit hole.

First of, a block in C is defined by { ... }. Identifiers defined inside this block have scope visibility / lifetime (used from now on interchangeable) limited to that block. The if (x) statement in Apple’s example above is creating such a C block, in which a struct is created and that struct is assigned to (Objective-C) block (called closures from now on for easier differentiation).
Every C block creates a new visibility scope were stack variables are stored (stack area) similar to stack frames. Which means after the block is closed it is not save any more to access these memory locations.

Closures are (apparently) the only Objective-C objects that start on the stack, the problem with that is, that the visibility is gone after the closing brace of the if-then-else and hence the block is lost. So the block has to be “saved” by copying it from the stack to the heap before the C block is finished.

Compilers

If you run the example code from Apple you will realise, that the code works flawless. It does not crash with a dreaded segfault and it even behaves exactly as you would expect it to.
Why? This is because clang does not reuse stack areas that were previously used and therefore nothing overwrite the memory location with something different (assuming you are not doing it from a different thread). The situation looks different if you are using gcc with the -O2 flag. gcc then reuses stack areas and overwrites your stack area. Since gcc is not capable of closures and clang doesn’t reuse stack areas you might be never run actually into a problem (There is a caveat tought[1]). This behaviour is, though, just an implementation detail that might change or vary from compiler to compiler and therefore you should not bet on it, it might change.
You can find some demo source code here that shows gcc -O0 versus gcc -O2.

Closures inside of an Array

A time where you run into problems is, when you try to save closures in an array like this:

typedef int(^Blocky)(void);
Blocky b[3];

for (int i=0; i<3; i++) {
    b[i] = ^{ return i;};
}
for (int i=0; i<3; i++) {
    printf("b %d", b[i]());
}

Code

The output is “2 2 2” instead of the expected “1 2 3”. This is because the stack area used for the for loop is the same for all iterations and therefore every new created closures overwrites the closures created in the previous iteration. In b[1], b[2] and b[3]is just a pointer stored to the closure and since the place of creation on the stack was the same for all three closures the pointer is the same which leads tob[1]==b[2]==b[3]`.

I wrote a small program that shows the different behaviours of closures on stack, closures on heap and blocks that use different stack areas.

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
    @autoreleasepool {
        
        typedef int(^Block)(void);
        
        void *p0, *p1;
        
        Block blockOnStack[3];
        Block blockOnHeap [3];
        
        for (int i=0; i<3; i++) {
            int int1 = 5;
            int int2 = 10;
            Block closure = ^{ return i; };
            
            blockOnStack[i] =             closure;
            blockOnHeap [i] = Block_copy( closure );
            
            printf("closure pointer:     %p\n",                blockOnStack[i] );
            printf("Block_copy pointer:                 %p\n", blockOnHeap [i] );
        }
                
        printf("\nExecuting blocks from the stack\n");
        for (int i = 0; i < 3; i++) {
            printf("pointer b[%d]: %p\n", i, blockOnStack[i]   );
            printf("Execute b[%d]: %d\n", i, blockOnStack[i]() );
        }
        printf("\nExecuting blocks from the heap\n");
        for (int i = 0; i < 3; i++) {
            printf("pointer b[%d]: %p\n", i, blockOnHeap[i]   );
            printf("Execute b[%d]: %d\n", i, blockOnHeap[i]() );
        }
        printf("\nC blocks\n");
        // "normal" C block scope 1
        {
            int blockInt0 = 5;
            p0 = &blockInt0;
        }

        // "normal" block scope 2
        {
            int blockInt1 = 10;
            p1 = &blockInt1;
        }

        printf("p0 = %p\np1 = %p\n", p0, p1);
        
        return 0;
    }
}
Every closure that is created inside the
for loop is created at the exact same
memory location on the stack.

The copied closures on the heap all have
different pointer addresses

closure pointer:     0x7fff54850bf0
Block_copy pointer:                 0x7fe5eac07c70
closure pointer:     0x7fff54850bf0
Block_copy pointer:                 0x7fe5eac07ca0
closure pointer:     0x7fff54850bf0
Block_copy pointer:                 0x7fe5eac07cd0
Stack pointers, all same ^^^^^^^^^^
Heap pointers, all distinct         ^^^^^^^^^^^^^^

Executing blocks from the stack
pointer b[0]: 0x7fff54850bf0
Execute b[0]: 2
pointer b[1]: 0x7fff54850bf0
Execute b[1]: 2
pointer b[2]: 0x7fff54850bf0
Execute b[2]: 2

Executing blocks from the heap
pointer b[0]: 0x7fe5eac07c70
Execute b[0]: 0
pointer b[1]: 0x7fe5eac07ca0
Execute b[1]: 1
pointer b[2]: 0x7fe5eac07cd0
Execute b[2]: 2

C blocks
Unlike the for loop C block scopes create a new stack
area for every visibility scope.
Unless compiled with e.g. gcc -O2
Remember: This is a implementation detail!!!
p0 = 0x7fff54850be4
p1 = 0x7fff54850be0

The code and output can be found for easy reading and copying in this gist.


  1. there always is  ↩

Posted in computer | Tagged , , , , , , , , | Leave a comment

Property: strong and copy

Property: strong and copy

//
//  main.m
//  strong_retain_copy
//
//  Created by Christopher Loessl on 25/02/14.
//  Copyright (c) 2014 Christopher Loessl. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (strong, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *nick;

@end

@implementation Person

@end

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        Person *per = [[Person alloc] init];
        NSMutableString *aName = [NSMutableString stringWithString:@"Christopher"];
        
        // The pointer "per.name" is changed.
        // "per.name" points at the same location as "someName" afterwards
        per.name = aName;
        
        // This is equal to
        // per.address = [someName copy];
        // Therefore the points are not the same afterwards
        per.nick = aName;
        
        // Changing "someName" to
        [aName setString:@"hashier"];
        
        NSLog(@"per.name   : %@", per.name);
        NSLog(@"per.nick   : %@", per.nick);
        NSLog(@"someName   : %@", aName);
        NSLog(@"\nPointer 1: %p\nPointer 2: %p\nPointer 3: %p", per.name, per.nick, aName);
        
    }
    return 0;
}

You can find this code in my github gists here for easy copy and compile[1].

The code is commented so you should really quickly see what the difference between copy and strong is doing here. By marking the pointer copy the object is copied during assignment and not just the pointer is copied over. For that to work, the NSCopying has the be implemented for that class. Luckily NSString, NSDictionary, and many others already support this protocol.

So now after you know what it makes for a difference with pointers, let’s see when you would want to use one over the other.

Even though per.name is NSString and should not be mutable it is possible to alter it through the 2nd pointer to the same address which is a NSMutableSring pointer. This said you can use copy to help you prevent this kind of trap so you might always want to use copy if the immutable class you are using conforms to NSCopying.

On the other hand, if you keep good track of your pointers and you know what you are doing, this could save you time during assignment because the assignment is much faster than copying the whole object [2]. So if you are only using immutable objects pointer assignments can help get some more speed. But remember

Premature optimization is the root of all evil [Knuth]


  1. clang -std=c99 -framework Foundation <file.m>  ↩

  2. Depending of the implementation of the object, this might be a shallow or deep copy.  ↩

Posted in computer | Tagged , , , , , | Leave a comment

Multiple Xcode targets and tests

Multiple Xcode targets

  • Go to targets -> Select target -> Duplicate (I duplicated a target which name was “tests”)
  • Rename the target to whatever you want (I use “Tooth” here)
  • Go to “Manage Schemes” and delete the scheme with the old name (“tests copy”) and click on “Autocreate Schemes Now”
  • Rename the “tests copy-Info.plist” to “Tooth-Info.plist” in your “Project Navigator” (or the path where Xcode can find the .plist file)
  • (If you need a different .pch file, you have to duplicate it in finder and add it to your project, otherwise “Tooth” will use the same .pch file as “tests”)
  • Go to the “Build Settings” of your new target and make sure that you check the following key value pairs:
    • Info.plist File: Change from “tests copy-Info.plist” to “Tooth-Info.plist”
    • Product Name: Change from “tests copy” to “$(TARGET_NAME)”
    • Prefix Header: Change accordingly if you need a different .pch file and created it earlier
    • Preprocessor Macros
      • Add something like “TOOTH=1” to your “Tooth” target and “TESTS=1” to your “tests” target (in Debug and Release)

If your project doesn’t build (or link) any more now, just reopen Xcode.

This is how you can decide in which target you are inside your code:

#if TESTS
    NSLog(@"I'm the tests target");
#elif TOOTH
    NSLog(@"I'm the Tooth target");
#else
    NSLog(@"Error: You added a new target and didn't set the Macros");
#endif

Adding a new test target

Of course you want to be able to write tests for your new target as well.

  • Go to the “Test Navigator”
  • On the bottom left click the “+” sign and chose “New Test Target…”
  • Select the Target you want to build tests for
  • WAIT! Don’t worry that you don’t see any tests for the new test target, just wait…. until it’s there, or restart Xcode
  • Right click on it and enable your test target
  • Go to “Build Settings” and select your tests target
    • Framework Search Path: Add “$(SRCROOT)” otherwise you will get errors with Frameworks like Crashlytics that it can’t find #import “Crashlytics/Crashlytics.h” (I add this as a project key value so I don’t have to do it for every new test target)
  • Start writing tests (:
Posted in computer | Tagged , , , , , , , | Leave a comment

mdfind & mdls & Spotlight

Searching for files with Spotlight is awesome and you can actually use the power of Spotlight even in the console. But first let me show you some nice features of Spotlight.

Spotlight

Searching for all images that contain “me”, are of kind image and were taken with flash:

mdfind kind:image flash:1  

Spotlight supports a whole lot of these search fields like, duration, pixel height, width, last opened, ISO speed, aperture, exposure time and so forth for a full list check this PDF.

mdfind

Now let’s move over to the console. Here you can do this cool stuff with a tool called mdfind.

Let’s find all audio files that are longer than 10 minutes:

$ mdfind -interpret 'duration:>=600 kind:music'

-interpret interprets the search string as if you typed it into Spotlight. mdfind supports another mode in which you can search on fields of the meta information directly.

$ mdfind -literal 'kMDItemDurationSeconds > 600 && kMDItemContentTypeTree == public.audio'

All mp3s that are longer than 10 minutes:

$ mdfind 'kMDItemDurationSeconds > 600 && kMDItemKind = "MPEG Audio Layer 3"'

All ATP podcasts:

$ mdfind '(kMDItemAuthors == "atp"cdw)'

cdw stands for:

  • ignore case
  • ignore diacritical
  • word based

All by the 5by5 network

$ mdfind 'kMDItemAuthors = "*5by5.tv*"'

Both are of course possible in Spotlight as well by simply searching for:

author:atp
author:5by5

Find all pictures taken with an iPhone 4S on the last day of the year 2011 and the first day of 2012. The range includes the from date but not the until date.

$ mdfind 'kind:image created:31/12/11-2/1/12 model:"iPhone 4S"'

mdls

But how to figure out these strange looking search fields, that’s where mdls comes into play.

$ mdls <file>

Prints out all meta information fields for that file. With mdfind you can then search for those fields.

If you are curious about all possible field values you can get them with

$ mdimport -X

and

$ mdimport -A

Be warned, it is a lot of information.

Final note

It’s worth having a look at the man page of these commands and the help provided with mdfind -h because the information is not consistent. For example the man page doesn’t tell you about the -s flag which brings smart folders to the command line.

And for the curious how I came across mdfind. I stumbled upon that command while reading this blog post by Brett Terpstra.

Sources:
Spotlight reference
MacDevCenter about mdfind

Posted in computer | Tagged , , , , | Leave a comment

iTunes Link Maker

Create links for the iTunes Store, the App Store, the iBookstore, and the Mac App Store.

With Link Maker, you can create links to content on the iTunes Store, the App Store, the iBookstore, and the Mac App Store, and then place those links on your website or within your app.

via iTunes Link Maker.

Posted in computer | Tagged , , , | Leave a comment

iOS localization with iLocalize

I did it once and now I needed to do it again – and of course I forgot how to do it, so this time I’ll write it down how localisation of an iOS project works.

I don’t use nib files and all user facing strings are set in code with NSLocalizedStrings(…). If you are using nibs or need to translate strings in Storyboard and/or nib files approach might differ.

English is considered as the base language and Swedish as the translation.

1) This is the workflow if you added new NSLocalizedString(…) in your code:

  1. Have your project with NSLocalizedString
  2. run `genstrings -o en.lproj **/*.m` in the correct folder (zsh needed)
  3. start iLocalize
  4. “Project” -> “Update from files…” -> add the en.lproj/Localizable.strings -> “Update the project from a new version of these files”
  5. click “Update”
  6. translate

 

2) This is the workflow if you updated the sv.lproj/Localizable.strings files e.g. manually added them in vim or you had someone translate it for you

It might be always good idea to update your Base language first so you can directly see after important the Swedish Localizable.strings file which “Translation Keys” have changed and need updating or if the translator got everything.

  1. In iLocalize on the top left you choose (for this example) Swedish
  2. “Project” -> “Update from files…” -> select your sv.lproj/Localizable.strings file-> “Update a localised language from these files”
  3. Make sure in the box Swedish is selected
  4. Click “Update”
  5. translate
Posted in computer | Tagged , , , , , , | Leave a comment

git diff and objective c

When you are writing Objective-C code and using git you probably realised that the `git diff` is not mentioning the function name in which the change occurred. This can easily be changed by just running following cmd inside your git repository:

echo "*.m diff=objc" >> .gitattributes

Source: https://gist.github.com/bjhomer/2473281

Posted in computer | Tagged , , , , | Leave a comment

Mavericks Wallpapers and Screen Saver images

Idea:

Have folder with all the Mavericks wallpapers and screen saver images but without wasting a lot of space. Why duplicate all of them, so you can set it as the folder that should be used for randomly choosing a background plus you can delete the ones you don’t want.

So we generate a folder in which we link all the default Mavericks wallpapers + screen saver images and set this as our folder to chose background images from, here’s the script:

$ mkdir folder
$ cd folder
$ find /Library/Desktop\ Pictures /Library/Screen\ Savers/Default\ Collections \( -name "*.jpg" -or -name "*.png" \) -and \! -path "*.thumbnails*" -and \! -path "*Solid Colors*" -exec ln -s "{}" . \;
Posted in computer | Tagged , , , | Leave a comment

Deep Wizardry: Stack Unwinding

Nice blog post about stack unwinding.

Posted in computer | Tagged , , | Leave a comment

Command to create installable OS X Mavericks 10.9 USB drive

Command to create installable OS X Mavericks 10.9 USB drive..

Posted in computer | Tagged , , , , , , | Leave a comment