Realm-cocoa: Swift 3 Crash when enumerating RLMResults using forEach, flatMap, enumerated(), but not basic for-in

Created on 11 Oct 2016  Â·  16Comments  Â·  Source: realm/realm-cocoa

Goals

Iterate through RLMResults using forEach, flatMap, enumerated(), etc.

Expected Results

No crash like with other Sequence types

Actual Results

Crashes EXC_BAD_ACCESS, no stack trace

Steps to Reproduce

Open attached project, pod install, and run
RealmTest.zip

Realm version: 2.0.2

Xcode version: 8.0

iOS/OSX version: 10

Dependency manager + version: Cocoapods 1.0.1

Blocked O-Community Pipeline-On-Hold T-Bug-Crash swift

Most helpful comment

We're encountering this in Xcode 10 / Swift 4.2, but only when running on 32-bit architectures (iPad 2, iPhone 4s, iPhone 5...) on either iOS 9 or iOS 10.

All 16 comments

Crash log:

(lldb) bt
* thread #1: tid = 0x1bb2edc, 0x000000010765ccbd libobjc.A.dylib`objc_retain + 13, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xe)
    frame #0: 0x000000010765ccbd libobjc.A.dylib`objc_retain + 13
    frame #1: 0x000000010666d726 RealmTest`protocol witness for Sequence.makeIterator() -> A.Iterator in conformance <A where ...> RLMResults<A> + 38 at RLMSupport.swift:0
    frame #2: 0x0000000109989f76 libswiftCore.dylib`Swift.EnumeratedSequence.makeIterator () -> Swift.EnumeratedIterator<A.Iterator> + 134
  * frame #3: 0x000000010666b9ed RealmTest`ViewController.crashWithEnumerated(self=0x00007fc6f2607370) -> () + 173 at ViewController.swift:53
    frame #4: 0x000000010666aeae RealmTest`ViewController.viewDidLoad(self=0x00007fc6f2607370) -> () + 1006 at ViewController.swift:34
    frame #5: 0x000000010666b2f2 RealmTest`@objc ViewController.viewDidLoad() -> () + 34 at ViewController.swift:0

This crash happens when building the debug configuration, but not the release configuration. That suggests it may be due to a compiler bug.

Unassigning myself as I won't be able to look at this in the short term.

Any news on this? Having the same issue when calling RLMResults.prefix().
Realm: 2.1.1
Xcode: 8.1
Happens in debug configuration only.

News on this will be posted in this issue.

Any news on this? Having the same issue

Realm 2.4.0
XCode 8.2

The only workaround I've found is to run your code on a release configuration or with whole module optimization.

Definitely frustrating because stepping barely works, so a better solution would be awesome.

On Feb 9, 2017, at 7:42 PM, Jacky Li notifications@github.com wrote:

Any news on this? Having the same issue

Realm 2.4.0
XCode 8.2

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.

@jpstern whole module optimization. doesn't fix the crash for us.

Will try to create an RLMResult extension to reimplement those high-order functions.

I did a bit of reduction on the issue in hopes of filing a bug against the Swift project. Here's what I have so far (all with Xcode 8.2):

func globalFuncMakeIteratorGeneric<T : Sequence>(x: T) {
    let _ = x.makeIterator()
}

func globalFuncMakeIterator(x: RLMResults<RLMObject>) {
    let _ = x.makeIterator()
}

let dogs = Dog.allObjects()   // RLMResults<Dog>
// Okay
let _ = dogs.makeIterator()
// Okay
globalFuncMakeIterator(x: dogs)
// Crashes
globalFuncMakeIteratorGeneric(x: dogs)

I think the problem is that somehow the argument is not being properly retained when being passed into the generic version of the function. I'll do some more digging later to see if there are any characteristics of RLMResults<> that are relevant to this problem.

I reduced the problem further and filed https://bugs.swift.org/browse/SR-4234.

If anyone cares, I've attached a repro project (which does not depend upon Realm at all).

GenericIteratorBug.zip

Any Temporary workaround through which I can make use of higher order functions? I have tried running in release configuration too but it is crashing for me.

I've found that this solution works so far. I haven't throughly tested it but it beats constantly wrapping collection and casting the element.

/// RLMIterator sourced from https://github.com/realm/realm-cocoa/blob/52dbb71bfd8ed20d7b8813f3999aaa8cd71396e6/Realm/Swift/RLMSupport.swift#L53-63
public struct RLMIterator<T>: IteratorProtocol {
    private var iteratorBase: NSFastEnumerationIterator

    internal init(collection: RLMCollection) {
        iteratorBase = NSFastEnumerationIterator(collection)
    }

    public mutating func next() -> T? {
        return iteratorBase.next() as! T?
    }
}

public class RLMSequence<T: RLMObject>: Sequence {
    private let base: AnySequence<T>

    public var first: T? {
        return makeIterator().next()
    }

    public init(_ x: RLMArray<T>) {
        base = AnySequence({
            RLMIterator<T>(collection: x)
        })
    }

    public init(_ x: RLMResults<T>) {
        base = AnySequence({
            RLMIterator<T>(collection: x)
        })
    }

    public func makeIterator() -> AnyIterator<T> {
        return base.makeIterator()
    }

}

Call site:

RLMSequence(Dog.allObjects())

n.b. You may need to duplicate the init's to handle any other RLMCollection subclasses

I just moved over to Xcode 9 and migrated to swift 4 and am no longer having the issue.

Not sure if anything else changed though.

It still happens on Xcode 9 / Swift 4

let result:Results<Person> = Person.allObjects().filter("age > 20")
result.map{$0.name})

It only crashes when the result is updated in the meantime.

image

This helped me. I was getting the EXC_BAD_EXCEPTION (Maybe related to flatMap), during JSON Parsing by ObjectMapper. Maybe it's related to this issue.

We're encountering this in Xcode 10 / Swift 4.2, but only when running on 32-bit architectures (iPad 2, iPhone 4s, iPhone 5...) on either iOS 9 or iOS 10.

Was this page helpful?
0 / 5 - 0 ratings