13

For some reason while implementing an objects hashValue for use in other structures the program crashes. It seems to crash when I attempt to get the hashCode of any string object. It is extending a struct but by time the hashValue is used the field that is accessed is already defined. I stretched this by testing a string such as "TEST" and it still crashes. Integer hashValues such as the id field are fine. Any assistance would be appreciated.

Swift 1.2 Xcode 6.4

extension SwiftObject:Hashable{//Hashable inherits Equatable and used for sets
    var hashValue: Int {
        let prime:Int = 31;
        var result:Int = 17;
        result = prime * result + id.hashValue
        result = prime * result + name.hashValue
        var locationString:String = "\(location.latitude.hashValue), \(location.longitude.hashValue)"
        result = prime * result + locationString.hashValue
        return result
    }
}

func == (lhs: Object, rhs: Object) -> Bool {
    let primaryBool:Bool = lhs.id == rhs.id
    let secondaryBool:Bool = lhs.name == rhs.name
    let thirdBool:Bool = lhs.location.distance(rhs.location) == 0
    return primaryBool || (secondaryBool && thirdBool)
}

StackTrace:

* thread #1: tid = 0x6c2b4, 0x000000010f021af3 IphoneApplication`IphoneApplication.AppStruct.hashValue.getter : Swift.Int(self=IphoneApplication.AppStruct at 0x00007fff50befde8) + 2771 at IphoneApplication.swift:96, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x000000010f021af3 IphoneApplication`IphoneApplication.AppStruct.hashValue.getter : Swift.Int(self=IphoneApplication.AppStruct at 0x00007fff50befde8) + 2771 at IphoneApplication.swift:96
    frame #1: 0x000000010f02302b IphoneApplication`protocol witness for Swift.Hashable.hashValue.getter : Swift.Int in conformance IphoneApplication.AppStruct : Swift.Hashable in IphoneApplication + 651 at IphoneApplication.swift:88
    frame #2: 0x0000000111fc1aad libswiftCore.dylib`Swift._NativeSetStorage._bucket <A : Swift.Hashable>(Swift._NativeSetStorage<A>)(A) -> Swift.Int + 29
    frame #3: 0x0000000111fd071e libswiftCore.dylib`Swift._VariantSetStorage.nativeUpdateValue <A : Swift.Hashable>(inout Swift._VariantSetStorage<A>)(A, forKey : A) -> Swift.Optional<A> + 334
    frame #4: 0x0000000111fbb344 libswiftCore.dylib`Swift._VariantSetStorage.updateValue <A : Swift.Hashable>(inout Swift._VariantSetStorage<A>)(A, forKey : A) -> Swift.Optional<A> + 52
    frame #5: 0x0000000111fbb2c0 libswiftCore.dylib`Swift.Set.insert <A : Swift.Hashable>(inout Swift.Set<A>)(A) -> () + 144
    frame #6: 0x000000010f032592 IphoneApplication`IphoneApplication.FoursquarePlacesService.(result=0x00007fcfc87700d0, self=0x00007fcfca825c90) -> (IphoneApplication.WOMapUI, searchTerm : Swift.String) -> Swift.Set<IphoneApplication.AppStruct>).(closure #1) + 8162 at FoursquarePlacesService.swift:102
    frame #7: 0x000000010f032917 IphoneApplication`reabstraction thunk helper from @callee_owned (@owned QuadratTouch.Result) -> (@unowned ()) to @callee_owned (@in (result : QuadratTouch.Result)) -> (@out ()) + 23 at FoursquarePlacesService.swift:0
    frame #8: 0x000000010f02d171 IphoneApplication`partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned QuadratTouch.Result) -> (@unowned ()) to @callee_owned (@in (result : QuadratTouch.Result)) -> (@out ()) + 81 at FoursquarePlacesService.swift:0
    frame #9: 0x0000000111e19150 QuadratTouch`reabstraction thunk helper from @callee_owned (@in (result : QuadratTouch.Result)) -> (@out ()) to @callee_owned (@owned QuadratTouch.Result) -> (@unowned ()) + 32 at Task.swift:0
    frame #10: 0x0000000111e190f8 QuadratTouch`QuadratTouch.DataTask.(self=0x00007fcfcd004100, result=0x00007fcfc87700d0) -> () -> ()).(closure #1).(closure #1) + 232 at Task.swift:71
    frame #11: 0x0000000111e19187 QuadratTouch`reabstraction thunk helper from @callee_owned () -> (@unowned ()) to @callee_unowned @objc_block () -> (@unowned ()) + 39 at Task.swift:0
    frame #12: 0x00000001100a757f Foundation`__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
    frame #13: 0x000000010ffe80b2 Foundation`-[NSBlockOperation main] + 98
    frame #14: 0x000000010ffca774 Foundation`-[__NSOperationInternal _start:] + 645
    frame #15: 0x000000010ffca383 Foundation`__NSOQSchedule_f + 184
    frame #16: 0x0000000112e60614 libdispatch.dylib`_dispatch_client_callout + 8
    frame #17: 0x0000000112e48a1c libdispatch.dylib`_dispatch_main_queue_callback_4CF + 1664
    frame #18: 0x000000010f8841f9 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    frame #19: 0x000000010f845dcb CoreFoundation`__CFRunLoopRun + 2043
    frame #20: 0x000000010f845366 CoreFoundation`CFRunLoopRunSpecific + 470
    frame #21: 0x0000000113d02a3e GraphicsServices`GSEventRunModal + 161
    frame #22: 0x00000001109288c0 UIKit`UIApplicationMain + 1282
    frame #23: 0x000000010f027727 IphoneApplication`main + 135 at AppDelegate.swift:13
    frame #24: 0x0000000112e94145 libdyld.dylib`start + 1
3
  • Can you post the stack trace, please?
    – fumoboy007
    Commented Aug 26, 2015 at 19:55
  • Also, you don’t need to specify the types when defining those variables because Swift will infer the type from the value you are assigning to the variable.
    – fumoboy007
    Commented Aug 26, 2015 at 19:58
  • I am beginning to believe it is an issue with integer overflow
    – kdgwill
    Commented Aug 26, 2015 at 21:32

1 Answer 1

21

Update (Swift 4.2+)

If you do need to manually implement the Hashable conformance for some reason, upgrade to Swift 4.2+ to adopt the new Hashable protocol, which gives you an easy-to-use Hasher object that internally uses a well-designed hashing algorithm.

For example, the above hash function would be transformed into

func hash(into hasher: inout Hasher) {
   hasher.combine(id)
   hasher.combine(name)
   hasher.combine(location)
}

Update (Swift 4.1+)

Upgrade to Swift 4.1 to gain compiler support for automatic synthesis of Hashable and Equatable conformance! See the Swift Evolution proposal for more details.


Original Answer

Yup, this looks like integer overflow. You can try using the overflow versions of the multiplication and addition operators: &* and &+.

Read more in The Swift Programming Language book.

7
  • 1
    This exactly fixed the issue thank you, for the fix and the link
    – kdgwill
    Commented Aug 26, 2015 at 23:12
  • @kdgwill My pleasure!
    – fumoboy007
    Commented Aug 26, 2015 at 23:18
  • Calling combine here is wrong. Call hash(into:). See the relevant WWDC 2018 video.
    – matt
    Commented Jul 8, 2018 at 20:39
  • @matt That’s not what the documentation says: “In your hash(into:) implementation, call combine(_:) on the provided Hasher instance with the essential components of your type.” And I’m pretty sure the implementation of combine(_:) just calls hash(into:).
    – fumoboy007
    Commented Jul 8, 2018 at 21:13
  • 2
    The Swift documentation and WWDC session are both right. hasher.combine(foo) and foo.hash(into: &hasher) are completely equivalent; feel free to use whichever form you prefer. Commented Jul 9, 2018 at 11:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.