Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9098971
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 17, 20262026-06-17T00:29:45+00:00 2026-06-17T00:29:45+00:00

I am trying to put some complex computations on a background thread using dispatch_async

  • 0

I am trying to put some complex computations on a background thread using dispatch_async but the objects I am using in the blocks seem to be overreleased. I am using ARC so I assumed that I do not have to care much about retain and release, but either I missed something important or ARC overreleases objects in my case.

The problem only appears if

  • I call dispatch_async creating a block in a for loop
  • I reference an object in the block created outside of the block
  • the loop does at least two iterations (thus at least two blocks are created and added to the queue)
  • a RELEASE build configuration is used (so it’s probably related to some optimization)

It does not seem to matter

  • whether it is a serial or concurrent queue
  • what kind of object is used

This question is not about blocks being release in the RELEASE configuration (as in iOS 5 blocks crash only with Release Build), but the objects referenced in the block being overreleased.

I created a small example using an NSURL object:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSURL *theURL = [NSURL URLWithString:@"/Users/"];
    dispatch_queue_t myQueue = dispatch_queue_create("several.blocks.queue", DISPATCH_QUEUE_SERIAL);

    dispatch_async(myQueue, ^(){
        NSURL *newURL = [theURL URLByAppendingPathComponent:@"test"];
        NSLog(@"Successfully created new url: %@ in initial block", newURL);
    });

    for (int i = 0; i < 2; i++)
    {
        dispatch_async(myQueue, ^(){
            NSURL *newURL = [theURL URLByAppendingPathComponent:@"test"];
            NSLog(@"Successfully created new url: %@ in loop block %d", newURL, i);
        });
    }
}

The first block which is not in the for-loop will work without issues. As will the second if the loop has only one iteration. In the given example however it does two iterations and will crash if run with a RELEASE configuration. Enabling NSZombie in the scheme outputs this:

2013-01-07 23:33:33.331 BlocksAndARC[17185:1803] Successfully created new url: /Users/test in initial block
2013-01-07 23:33:33.333 BlocksAndARC[17185:1803] Successfully created new url: /Users/test in loop block 0
2013-01-07 23:33:33.333 BlocksAndARC[17185:1803] *** -[CFURL URLByAppendingPathComponent:]: message sent to deallocated instance 0x101c32790

with the debugger stopping at the URLByAppendingPathComponent call in the block in the for-loop.

When using a concurrent queue the failing call will actually be a release call with _Block_release in the call stack:

2013-01-07 23:36:13.291 BlocksAndARC[17230:5f03] *** -[CFURL release]: message sent to deallocated instance 0x10190dd30
(lldb) bt
* thread #6: tid = 0x3503, 0x00007fff885914ce CoreFoundation`___forwarding___ + 158, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x00007fff885914ce CoreFoundation`___forwarding___ + 158
    frame #1: 0x00007fff885913b8 CoreFoundation`_CF_forwarding_prep_0 + 232
    frame #2: 0x00007fff808166a3 libsystem_blocks.dylib`_Block_release + 202
    frame #3: 0x00007fff89f330b6 libdispatch.dylib`_dispatch_client_callout + 8
    frame #4: 0x00007fff89f38317 libdispatch.dylib`_dispatch_async_f_redirect_invoke + 117
    frame #5: 0x00007fff89f330b6 libdispatch.dylib`_dispatch_client_callout + 8
    frame #6: 0x00007fff89f341fa libdispatch.dylib`_dispatch_worker_thread2 + 304
    frame #7: 0x00007fff852f0cab libsystem_c.dylib`_pthread_wqthread + 404
    frame #8: 0x00007fff852db171 libsystem_c.dylib`start_wqthread + 13

but this is probably just due to slightly different timing.

I think both errors indicate that the NSURL object referenced by theURL is overreleased. But why is that? Did I miss something or is that a bug in the combination of ARC and blocks?

What I would expect to happen is that either before the dispatch_async call or in the implementation of dispatch_async (anyway: inside the for-loop, once for each dispatch_async-call) every variable referenced inside the block is retained and it is released at the end of (but in) the block.

What actually seems to happen is that the variables are retained once for an occurrence of dispatch_async in the code but release is called at the end of the block so whenever it is executed, which leads to more release calls than retain calls in a loop.

But maybe I’m overlooking something. Is there a better explanation? Did I misuse blocks or ARC in some way or is this a bug?

EDIT: I tried @Joshua Weinberg’s suggestion of copying the referenced variable to a local one inside the for-loop. It work’s in the given sample code, but does not work, when a function call is involved:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSObject *theObject = [[NSObject alloc] init];

    [self blocksInForLoopWithObject:theObject];
}

-(void)blocksInForLoopWithObject:(NSObject *)theObject
{
    dispatch_queue_t myQueue = dispatch_queue_create("several.blocks.queue", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 2; i++)
    {
        NSObject *theSameObject = theObject;
        dispatch_async(myQueue, ^(){
            NSString *description = [theSameObject description];
            NSLog(@"Successfully referenced object %@ in loop block %d", description, i);
        });
    }
}

So why does it work in on case, but not in the other? I don’t see the difference.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-17T00:29:46+00:00Added an answer on June 17, 2026 at 12:29 am

    I was just able to reproduce this when I tried it out. Your diagnosis seems spot on and as far as I can tell is an issue with some optimization on how the blocks get copied/retain their scope going awry. Seems radar worthy.

    As far as what you can do to work around this.

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        NSURL *theURL = [NSURL URLWithString:@"/Users/"];
        dispatch_queue_t myQueue = dispatch_queue_create("several.blocks.queue", DISPATCH_QUEUE_SERIAL);
    
        dispatch_async(myQueue, ^(){
            NSURL *newURL = [theURL URLByAppendingPathComponent:@"test"];
            NSLog(@"Successfully created new url: %@ in initial block", newURL);
        });
    
        for (int i = 0; i < 2; i++)
        {
            NSURL *localURL = theURL;
            dispatch_async(myQueue, ^(){
                NSURL *newURL = [localURL URLByAppendingPathComponent:@"test"];
                NSLog(@"Successfully created new url: %@ in loop block %d", newURL, i);
            });
        }
    }
    

    Copying that to the stack forces the block to recapture it each time and enforces your intended memory semantics.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to put some time-consumed database operations into the background thread with the
I'm trying to put some sites i crawled into a shelve, but the shelve
I'm trying to put some HTML content inside <content:encoded> tags using ROME and its
Hello everyone I've been trying to put some objects in an ASP.NET list box
I'm trying to put some content inside my TabItem, but I can't add a
I'm trying to put some objects in the screen at random positions. I use
I using rails3 and trying to build some complex associations. I have Product, Version
I'm trying to PUT some XML to a server, but the gist of it
I am trying to put some distributed caching into play, I'm using this indeXus.Net
I am trying to put some data in a list of custom objects. One

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.