pointer being freed was not allocated

I just started doing some calculations into a background thread by creating a custom serial dispatch_queue. (Xcode 7.1 beta)


Now sometimes when I move the mouse really fast I get an error "pointer being freed was not allocated" triggered inside drawRect of my custom view.

The error occures inside a switch over an enum.

switch state {
        case .Hide:
            return
        case .Show(let elements):
            CGContextSetRGBFillColor(context, 1, 0.8, 0.2, 1)
            CGContextSetRGBStrokeColor(context, 0.8, 0.5, 0.1, 1)
            CGContextSetLineWidth(context, 1)
            for e in elements {
                drawDotAt(context, position: p.position, size: 5)
            }
            CGContextDrawPath(context, .FillStroke)
}

The enum is defined as:

public enum State {
        case Hide
        case Show([Element])
}

Element itself is a struct and looks somthing like this:

struct Element {
  position: Vec2
  label: String
  radius: Double
}



As you can see there are only structs and enums involved.

For me the error looks like a race codition (the background task modifies the state) but until now I thought that structs and enums are threadsafe.


Now my question is: Is this the compiler's fault generating wrong code? Or is it my fault because I need my own locking mechanism preventing the drawRect code accessing the state value while the background task is modiying it?


I know that the code above is very superfacial and may be not enough information to debug the error but before I try building a working example I would like to have a more general answer on this problem: when getting a "pointer being freed was not allocated" error, is this something I have to take care of when doing multithreaded stuff? If yes: What is a general approach to solve this? some kind of double buffering? If not: Can I assume it is a compiler error?

Answered by jawbroken in 60030022

Well, as a simple example, Swift Arrays (such as your [Element]) are implemented using referenced storage as a copy-on-write optimisation. If you start writing to it from multiple threads, then you can definitely see cases where your writes are not reflected in the final array. I imagine, but don't know, that you might also be able to corrupt the internal bookkeeping for the referenced storage and see issues like the one you report. inout parameters are implemented, semantically, as read-modify-write so you can probably see similar issues even with simple structs. But again, I'm not sure if this is causing the problem you report, I'm just addressing the question of thread safety.

“I thought that structs and enums are threadsafe”


They aren't. Use GCD or similar to serialise access to your data.

Are you sure? I thought being threadsafe is one of the selling points of value types. In the case above the error occurs in the end of the for-loop. The loop only accesses the array (which should be a copy of the one modified by the other thread) and it's elements (which should be copies aswell).


One weird thing is that the error occurs always on the same line even though I have multiple of those "states" which get modified by one thread and drawn by another.

I don't have any idea about your specific issue, and I'm not sure there's enough context in your post to diagnose it, but yes, structs and enums are not thread-safe. Did you read somewhere that they are? Perhaps you are confused with immutable objects, which can be thread-safe.

For example in this Stackoverflow thread: stackoverflow.com/a/24232845/1533291


"With Structs there is no need to worry about memory leaks or multiple threads racing to access/modify a single instance of a variable."

"Structs are much safer and bug free, especially in a multithreaded environment"

"automatically threadsafe due to not being shareable"


And by my own reasoning I would expect no aliasing to occure with pure value-semantics. So I can not see how a value would be double-freed if it is not really shared. I would like to give a more complete example of my code but I guess I need to first understand the problem in order to be able to extract the relevant code.


Update:


I have tried to compose some working code reproducing the problem:

import Foundation

struct Vec2d {
    let x : Double
    let y : Double
}

extension Vec2d : CustomDebugStringConvertible {
    var debugDescription : String {
        return String("Vec2d(%.2f, %.2f)", x, y)
    }
}

enum State {
    case Hide
    case Show([Vec2d])
}


class Controller {
    var state = State.Hide
}

let myController = Controller()

// do some claculations in a background thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [myController]
    while true {
        let r : Int =  Int(arc4random_uniform(100))
        if r < 20 {
           // create some points
            var points : [Vec2d] = Array<Vec2d>()
            for i in 0...r {
                points.append(Vec2d(x: Double(i), y: Double(i)))
            }
           // put the points into the controller
            myController.state = .Show(points)
        } else {
            // disable the controller
            myController.state = .Hide
        }
    }
}


while true {
    let r : Int =  Int(arc4random_uniform(100))
    if r < 20 {
       // get the controller state
        let currentState = myController.state
        switch currentState {
        case .Hide:
            print("Hidden")
        case .Show(let points):
           // If the controller is enabled, print all the current points
            for p in points {
                print(p)
               // sometimes EXC_BAD_ACCESS is triggered here
            }
        }
    }
}
Accepted Answer

Well, as a simple example, Swift Arrays (such as your [Element]) are implemented using referenced storage as a copy-on-write optimisation. If you start writing to it from multiple threads, then you can definitely see cases where your writes are not reflected in the final array. I imagine, but don't know, that you might also be able to corrupt the internal bookkeeping for the referenced storage and see issues like the one you report. inout parameters are implemented, semantically, as read-modify-write so you can probably see similar issues even with simple structs. But again, I'm not sure if this is causing the problem you report, I'm just addressing the question of thread safety.

Thank you. I am not writing to a single array from multiple threads. I am creating an array in one thread, then assign this array to a property, then read this property from another thread. Then creating a new array in the first thread and then assign this new array to the property. But your explanation seems to be in the right direction nevertheless and lead me to solve the problem. The internal reference counting of the array's buffer seems to be not atomic so I needed to syncronize the assignment of the array to the property.


Here is the example from above. Now working as expected:


import Foundation
struct Vec2d {
    let x : Double
    let y : Double
}
extension Vec2d : CustomDebugStringConvertible {
    var debugDescription : String {
        return String("Vec2d(%.2f, %.2f)", x, y)
    }
}
enum State {
    case Hide
    case Show([Vec2d])
}
class Controller {
    var state = State.Hide
}
let myController = Controller()
let printingQueue = dispatch_queue_create("de.laszlokorte.queue", nil)
let workingQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(workingQueue) { [myController]
    while true {
        let r : Int =  Int(arc4random_uniform(100))
        print(r)
        if r < 20 {
            var points : [Vec2d] = Array<Vec2d>()
            for i in 0...r {
                points.append(Vec2d(x: Double(i), y: Double(i)))
            }
           // the assignment must not be done concurrent but must be syncronized with the reading thread
            dispatch_sync(printingQueue) {
                myController.state = .Show(points)
            }
        } else {
           // the assignment must not be done concurrent but must be syncronized with the reading thread
            dispatch_sync(printingQueue) {
                myController.state = .Hide
            }
        }
    }
}
while true {
    let r : Int =  Int(arc4random_uniform(100))
    if r < 20 {
        dispatch_sync(printingQueue) {
            let currentState = myController.state
            switch currentState {
            case .Hide:
                print("Hidden")
            case .Show(let points):
                for p in points {
                    print(p, terminator: "")
                }
                print("")
            }
        }
    }
}
pointer being freed was not allocated
 
 
Q