Memory leak problem with fetchRequest.affectedStores #96

Closed
opened 2025-12-29 15:24:32 +01:00 by adam · 11 comments
Owner

Originally created by @laeroah on GitHub (Nov 2, 2016).

There's a memory leak with this line:
From.swift 214: fetchRequest.affectedStores = stores
This can be reproduced on the demo app.
Since this happens every time we make a fetch, it's actually pretty serious and add up the leaked memory quickly.

screen shot 2016-11-02 at 4 22 20 pm

Please help. Thanks.

Originally created by @laeroah on GitHub (Nov 2, 2016). There's a memory leak with this line: `From.swift 214: fetchRequest.affectedStores = stores` This can be reproduced on the demo app. Since this happens every time we make a fetch, it's actually pretty serious and add up the leaked memory quickly. <img width="816" alt="screen shot 2016-11-02 at 4 22 20 pm" src="https://cloud.githubusercontent.com/assets/1928509/19945919/96427d4e-a118-11e6-86eb-7eaee4c5d248.png"> Please help. Thanks.
adam added the in progresshelp wantedios/compiler bug labels 2025-12-29 15:24:32 +01:00
adam closed this issue 2025-12-29 15:24:32 +01:00
Author
Owner

@JohnEstropia commented on GitHub (Nov 3, 2016):

Yes we already know there is an ARC bug from
https://github.com/JohnEstropia/CoreStore/issues/100
https://github.com/JohnEstropia/CoreStore/issues/101
https://github.com/JohnEstropia/CoreStore/issues/110

So to avoid crashing right now we're choosing the lesser of two evils, erring on the side of leaks.

Please submit a bug report to Apple so that this gets fixed. (This bug existed since iOS 6, 2013)

@JohnEstropia commented on GitHub (Nov 3, 2016): Yes we already know there is an ARC bug from https://github.com/JohnEstropia/CoreStore/issues/100 https://github.com/JohnEstropia/CoreStore/issues/101 https://github.com/JohnEstropia/CoreStore/issues/110 So to avoid crashing right now we're choosing the lesser of two evils, erring on the side of leaks. Please submit a bug report to Apple so that this gets fixed. (This bug existed [since iOS 6, 2013](http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified))
Author
Owner

@laeroah commented on GitHub (Nov 3, 2016):

Thanks for explaining. If I skip this line fetchRequest.affectedStores = stores until it's fixed, do you see any problem there? I'm only using one persistent store in my app right now.
Do you happen to know someone have already logged an issue to Apple regarding this?

@laeroah commented on GitHub (Nov 3, 2016): Thanks for explaining. If I skip this line `fetchRequest.affectedStores = stores` until it's fixed, do you see any problem there? I'm only using one persistent store in my app right now. Do you happen to know someone have already logged an issue to Apple regarding this?
Author
Owner

@JohnEstropia commented on GitHub (Nov 3, 2016):

I tried avoiding that optimization because it will mess up iCloud stores and multi-configuration setups, but if your project just uses a single persistent store it should be fine.

Just for reference, may I know what iOS version you are seeing this?

@JohnEstropia commented on GitHub (Nov 3, 2016): I tried avoiding that optimization because it will mess up iCloud stores and multi-configuration setups, but if your project just uses a single persistent store it should be fine. Just for reference, may I know what iOS version you are seeing this?
Author
Owner

@laeroah commented on GitHub (Nov 3, 2016):

iOS 10.0.1

@laeroah commented on GitHub (Nov 3, 2016): iOS 10.0.1
Author
Owner

@JohnEstropia commented on GitHub (Nov 3, 2016):

Can you try to put this on top of setAffectedStores and see if it improves a little?

- (void)setAffectedStores:(NSArray<NSPersistentStore *> *_Nullable)affectedStores {

    if ([self.safeAffectedStores isEqualToArray:affectedStores]) {

        return;
    }

If you're seeing this on ListMonitor's fetch which reuses it's existing NSFetchRequest we might be able to avoid resetting the affectedStores.

@JohnEstropia commented on GitHub (Nov 3, 2016): Can you try to put this on top of `setAffectedStores` and see if it improves a little? ``` - (void)setAffectedStores:(NSArray<NSPersistentStore *> *_Nullable)affectedStores { if ([self.safeAffectedStores isEqualToArray:affectedStores]) { return; } ``` If you're seeing this on ListMonitor's fetch which reuses it's existing NSFetchRequest we might be able to avoid resetting the affectedStores.
Author
Owner

@laeroah commented on GitHub (Nov 3, 2016):

No ... still see the leaks

@laeroah commented on GitHub (Nov 3, 2016): No ... still see the leaks
Author
Owner

@colinmorelli commented on GitHub (Nov 12, 2016):

@JohnEstropia If the leak is caused by the CFBridgingRetain that was added to CSFetchRequest in setAffectedStores, is there any reason this can't be avoid by simply adding a CFBridgingRelease when either a) overwriting the affected stores with a new array, or b) in deinit/dealloc

Edit:
I misread how it works at first, but would it still not work to:

  • Implement setAffectedStores: call CFBridgingRelease on the current value of affectedStores
    and CFBridgingRetain on the provided value
  • Implement dealloc to call CFBridgingRelease on the value of affectedStores
@colinmorelli commented on GitHub (Nov 12, 2016): @JohnEstropia If the leak is caused by the `CFBridgingRetain` that was added to `CSFetchRequest` in `setAffectedStores`, is there any reason this can't be avoid by simply adding a `CFBridgingRelease` when either a) overwriting the affected stores with a new array, or b) in deinit/dealloc _Edit_: I misread how it works at first, but would it still not work to: - Implement `setAffectedStores:` call `CFBridgingRelease` on the current value of `affectedStores` and `CFBridgingRetain` on the provided value - Implement `dealloc` to call `CFBridgingRelease` on the value of `affectedStores`
Author
Owner

@JohnEstropia commented on GitHub (Nov 12, 2016):

@colinmorelli The leak only happens "sometimes". When it doesn't, the deallocation happens properly. So we are left with these options:

  • leak some times and behave correctly some times, or
  • behave correctly some times but crash with over-deallocating some times

We can't predict when to call exactly when to call CFBridgingRetain and CFBridgingRelease because we don't know when CoreData fails to do ARC properly, and even if we do know, we can't handle it anyway because they are all internal processing.

@JohnEstropia commented on GitHub (Nov 12, 2016): @colinmorelli The leak only happens "sometimes". When it doesn't, the deallocation happens properly. So we are left with these options: - leak some times and behave correctly some times, or - behave correctly some times but crash with over-deallocating some times We can't predict when to call exactly when to call CFBridgingRetain and CFBridgingRelease because we don't know when CoreData fails to do ARC properly, and even if we do know, we can't handle it anyway because they are all internal processing.
Author
Owner

@colinmorelli commented on GitHub (Nov 12, 2016):

Got it. That clears things up.

Well, I hate to even suggest this, but just to throw out all options, you could try to create an NSArray subclass, disable ARC (for the one file only), which would allow you to override retain and release, and probably detect this issue. I haven't personally tested this, but I would imagine with access to those method calls, you might be able to find out where/why this happens. Possibly even be able to figure out a workaround to it that avoids a leak.

It may not work at all, but I figured I'd at least make the suggestion.

@colinmorelli commented on GitHub (Nov 12, 2016): Got it. That clears things up. Well, I hate to even suggest this, but just to throw out all options, you could try to create an `NSArray` subclass, disable ARC (for the one file only), which would allow you to override `retain` and `release`, and probably detect this issue. I haven't personally tested this, but I would imagine with access to those method calls, you might be able to find out where/why this happens. Possibly even be able to figure out a workaround to it that avoids a leak. It may not work at all, but I figured I'd at least make the suggestion.
Author
Owner

@JohnEstropia commented on GitHub (Apr 24, 2017):

I changed the ListMonitor refetch method for CoreStore v4.
53ab140341
You can try it out in the corestore4_develop branch, although some code migrations from CoreStore 3 may need to be done.

@JohnEstropia commented on GitHub (Apr 24, 2017): I changed the ListMonitor refetch method for CoreStore v4. https://github.com/JohnEstropia/CoreStore/commit/53ab140341f412b3cf0efd09db32d850ea2a60ea You can try it out in the `corestore4_develop` branch, although some code migrations from CoreStore 3 may need to be done.
Author
Owner

@JohnEstropia commented on GitHub (Aug 23, 2017):

@laeroah Just an update, I got a follow-up from the Apple bug report that this issue was fixed on iOS 11. The workaround code that CoreStore is doing is not needed anymore (and in fact harmful) on iOS 11 devices, so this was fixed on CoreStore 4.1.1:
2912dcf010

@JohnEstropia commented on GitHub (Aug 23, 2017): @laeroah Just an update, I got a follow-up from the Apple bug report that this issue was fixed on iOS 11. The workaround code that CoreStore is doing is not needed anymore (and in fact harmful) on iOS 11 devices, so this was fixed on CoreStore 4.1.1: https://github.com/JohnEstropia/CoreStore/commit/2912dcf010e001f8e008e4ec4ade2ab5b5f51bc7
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore#96