Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EXC_BAD_ACCESS when convert Swift String to Data

Tags:

ios

swift3

Application crashes when calls this function in Release build (for Debug it works flawless)

func crashMe()
{
    func crashHelper(str: String) {}
    
    var crashString = "123"
    crashString.remove(at: crashString.startIndex)
    
    crashHelper(str: "\(crashString)")
    
    crashString.data(using: .ascii)
}

Almost always reproduces on real device and often on simulator (but not 100%) with either iOS 9 or 10

Removing any line from this function prevents crash

What do I do wrong or maybe it is some Swift bug?

It can crash in different places, one of crash logs:

0x02194b8a in swift_unknownRelease ()

0x020702c5 in _NSContiguousString.__deallocating_deinit ()

0x024cea26 in String.data(using : String.Encoding, allowLossyConversion : Bool) -> Data? ()

0x0007e04f in specialized AppDelegate.crashMe() -> ()

0x0007c31c in AppDelegate.crashMe() -> () [inlined] ()

like image 617
abagmut Avatar asked Mar 02 '17 22:03

abagmut


1 Answers

This is an update to my initial answer, even though it is more of an investigation report than answer.

I was able to reproduce the problem in a simple macOS command line utility in Release build. The content of main.swift follows.

import Foundation

func crashMe() {

    func crashHelper(str: String) {
//        print("crashHelper() got \(str)")  // line 1
        print("In crashHelper()!")  // line 2
//        var i = 123; i += 321; print("In crashHelper() the int is \(i)")  // line 3
    }

    var crashString = "123"
    crashString.remove(at: crashString.startIndex)
    crashHelper(str: "\(crashString)")

//    if let stringData = crashString.data(using: .ascii) {
//        print("stringData has \(stringData.count) bytes")
//    }
}

crashMe()
print("Success!!!")

Some observations:

  • The crash consistently happens in swift_unknownRetain when crashMe() is called.
  • If line 2 in crashHelper() is commented out, i.e. the function has an empty body, then the if block has to be uncommented to get a crash, which now happens at the crashString.data() call.
  • If line 1 and/or 3 is uncommented, then the program doesn't crash regardless of the presence of line 2.
  • crashHelper() doesn't have to be defined inside another function; it can be a top-level function, but placing it into a function makes crashing more likely.
  • Passing crashString without string interpolation to crashHelper() will resolve the aforementioned crashes.

Thus I would say this is a Swift bug in how string interpolation is implemented.

like image 168
Anatoli P Avatar answered Oct 08 '22 13:10

Anatoli P