last night my code worked. today, it is randomly failing with multiple EXC_BAD_ACESS errors

last night my code worked. today, it is randomly failing with multiple EXC_BAD_ACESS errors


it was throwing an error when I added an element to an existing array like this:

self.view?.node?.children += [node]


I replaced that code with :

if let aNode = self.view?.node{
     aNode.children.append(node)
}


and for 1 test it worked fine. But i got another error with another array in a completely unrealted section of the app.


then the next time I ran, trying to fix the other error... The code i replaced started throwing errors.


the only difference was that I ran the OS update last night. 10.12.6. Ok so I'm working with beta 2 of Xcode 9... I checked and ther eis an update: beta 4.

updated to that, cleaned the code, rebuilt... same error.


My code, which was written in Swift 4, which worked yesterday, compiles and has apparently hundreds of EXC_BAD_ACCRESS errors now.

what gives? any ideas? I have checked in code that the array exists, and the the object I am adding to it exists. there's nothing in my code that is changing that in any way, when I try to append the object to the array. and like I said: this is tested and working code, that until last night had been humming along happily in thousands of tests.

and I tried on High sierra. the offending code runs fine, but other errors show up.

had a longer description, But this WEBSITE is acting up. and won't let me post anything that's long.

How do you know that your App "has apparently hundreds of EXC_BAD_ACCESS errors now" ?

Can you locate precisely one and breakpoint just before, to see if you are trying to access a released object ?

May be the problem is node that you try to append ?

You say : "But i got another error with another array in a completely unrealted section of the app"

Are all the the EXC_BAD_ACCESS connected to operations on node ?

Can you show how you defined the different arrays ?

PS: of course, I think you did a clean build folder ?

I say apparently, because I don't know for certain, But I am getting these errors one right after another... doing things which are the meat and potatoes of programming.


I originally thought I was trying to access a released object. Here's the problem with that: I have changed no code. Last night the same code accessed an object that was not released. So I decided to check for the existence of the object Just before I try to add the element to the array.

if let aNode = self.view?.node{
  aNode.children.append(node)
}


aNode exists.

children is Not an Optional property.

@objc dynamic open  var children : [CNNode] = []

node is created just before this block of code. and I check to see if it was created.

if let node = NSKeyedUnarchiver.unarchiveObject(with: data ) as? CNNode


This error is not present in XCode beta 4, on High Sierra. But it is On Seirra 10.12.6.

what else is there?


here's the code for the other error:

override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        self.CNObjUpdated = true
    }


CNObjUpdated is a Bool property... in the same class that is setting it's value. It's not optional, and clearly the class has not been released, otherwise you couldn't be able to call it's methods.

@objc dynamic  open var CNObjUpdated : Bool = true


I expect (and this is why I said apparently) that if I were somehow magically able to clear these errors, I'd have the same thing throughout my app wherever I try to set a variable, or modify a collection.


I have cleaned the products, I have restarted, I have tried refactoring the code (which was successful for 1 test)

So you test


if let node = NSKeyedUnarchiver.unarchiveObject(with: data ) as? CNNode

before the block

if let aNode = self.view?.node{

aNode.children.append(node)

}


How are the 2 parts connected ? Like this ?


if let node = NSKeyedUnarchiver.unarchiveObject(with: data ) as? CNNode {
     if let aNode = self.view?.node {
       aNode.children.append(node)
     }
}


Can you show the larger peice of code.


Are the 2 parts

if let node

and

if let aNode


executed on the same thread ?

ok. here is how rediculous this is.


I went through the method and refactored it. adding copius comments. I built it. It ran.

then I hit one of the other bugs. So I went back and made changes to adjust that (I am currently writing new code, just nowhere near this stuff)


then I build and run again: same old bug.


so I did another test. I added another comment, built and run: nope.

then I added a line of code:

NSLog("stupid")


just before we get to the line that throws the error.(2 lines before)

and guess what? built, ran, and got past the error.


ran it again... nope, got the error again.


here is my current method in it's entirety.

    open override func performDragOperation(_ sender: NSDraggingInfo) -> Bool{
       
        /
        let pasteBoard = sender.draggingPasteboard()
       
        /
        let nodeTypes = ["bkTools.CNNode"]
        /
        if pasteBoard.canReadItem(withDataConformingToTypes: nodeTypes) {
            /
            for imageType in nodeTypes {
                /
                if let data = pasteBoard.data(forType:NSPasteboard.PasteboardType(rawValue: "bkTools.CNNode")) {
                    /
                    if let newNode = NSKeyedUnarchiver.unarchiveObject(with: data ) as? CNNode{
                        /
                        if let inputDescr = self.view?.node?.inputDescr{
                            /
                            if inputDescr.okInputTypes.contains(newNode.objType){
                                /
                                if let aNode = self.view?.node{
                                    /
                                    NSLog("stupid")
                                    aNode.addPipe(fromNode: newNode, toNode: aNode)
the next line is where we get the error.
                                    aNode.children.append(newNode)
                                }
                                self.view?.needsDisplay = true
                                return true
                            }
                        }
                       
                    }
                }
            }
        }

What happens if you comment out


aNode.addPipe(fromNode: newNode, toNode: aNode)


And to check, can you log newNode and aNode before and after


if let aNode = self.view?.node{
     NSLog("stupid") ; NSLog(aNode) ; NSLog(newNode)
     aNode.addPipe(fromNode: newNode, toNode: aNode)
     aNode.children.append(newNode)           // the next line is where we get the error.
     NSLog("after append") ; NSLog(aNode) ; NSLog(newNode)  
}

i just tried that.

the first run, it worked. the second run: nope. same error.


I'll try the NSLog thing.

NSLog Balks at NSLog(aNode) etc...


error message :

: Cannot convert value of type 'CNNode' to expected argument type 'String'


CNNode is a subclass of NSObject, with a bunch of properties. I'll try using one of those for the log

results:

2017-07-28 15:57:14.231687-0400 concrete[2147:112304] pre

2017-07-28 15:57:14.231730-0400 concrete[2147:112304] name

2017-07-28 15:57:14.231750-0400 concrete[2147:112304] name

2017-07-28 15:57:14.234081-0400 concrete[2147:112304] created a nodePipe, using node and properties init

2017-07-28 15:57:14.234398-0400 concrete[2147:112304] added the pipe, using from to method

name is the default name of the CNNode class.

here's the code:

if let aNode = self.view?.node{
                                    /
                                  
     NSLog("pre "); NSLog(aNode.objName) ; NSLog(newNode.objName)  ;
                                  
     aNode.addPipe(fromNode: newNode, toNode: aNode)
      aNode.children.append(newNode)
                                  
     NSLog("post "); NSLog(aNode.objName) ; NSLog(newNode.objName)  ;
}


those two other NSLogs, are notifications to me that two things have happened: I have sucessfully created a Pipe object, and then I have successfully added it to an array, IN THE aNode class, using the addPipe() method. So its driving me crazy having to worry about this object. because we Knwo it exists, and it doesn't fall apart when someone tries to add objects to it's arrays.


here's that method btw:

open func addPipe(fromNode: CNNode, toNode: CNNode){
        if toNode.inputDescr.okInputTypes.filter({$0 == fromNode.objType}).count > 0 {
            /
            var newProps : [String: CNObjProperty] = [:]
           
            let descr = toNode.inputDescr
            if let typeMods = descr.inputTypeModifiers[fromNode.objType]{
           
                for aProp in typeMods.keys{
                    let newProp = typeMods[aProp]?.copy() as! CNObjProperty
                   
                    newProps[aProp] = newProp
                }
               
                /
                let newPipe = CNNodeStackPipe(fromNode, newProps )
               
                /
                let antecedentNodes = newPipe.antecedentNodes()
                if antecedentNodes.contains(toNode) == false {
                    /
                    /
                    toNode.inputs += [newPipe]
                    self.nodePipes.append(newPipe)
                    NSLog("added the pipe, using from to method")
                }
            }
        }
    }

Yse, NSLog(aNode) is a bit brutal !


Do you run in simulator or on device ?


In simulator, you can print(aNode) ; you'll get an object reference at least.

And you can breakpoint to observe in debugger as well.

the forums are blocking me from responding.

my app is mac os x

OK, so you can use debugger to inspect objects.


Tell what you get (once the forum let you reply ?!?)

so. maybe I skipped mentioning this earlier. sorry.

as we go into the line

aNode.children.append(newNode)


every object is there. in the debugger everything is there. aNode is populated, newNode is populated. I've taken a look at the children in aNode, and it's there. The debugger is showing nothing wrong. Nothing at all.

This discussion isn't working. The fact that your code crashes easily is a gift. It's the rare crash that's hard to debug.


You have to realize that an invalid access to memory tends to indicate a memory management bug (or a buffer overrun, sometimes). Either way, the symptoms of the error depend on timing details and memory layout of your app. That means that the location/timing of the crash (which is usually long past the point of the actual bug) can vary if you update (say) the OS or the compiler.


But there's no point in flailing around randomly changing source code. Once you have an error, you need to investigate what went wrong. That means looking at the backtrace at the time of the crash (preferably with the debugger), trying to figure out exactly what went wrong. Also, if you run it again, does it crash in the exact same place? In a similar place? In a totally random place?

Hi Quincy... I'll just try to asnwer your questions.

does it crash in the same place?


uhhh... no. If I make a change (and the jury is out on Just what changes count, once I added comments. but tthat doesn't always work) then I get a single build and run instance, where we never see this particular bug at all. But we get another one.


on a different system running High Seirra Beta, we never see the first bug. we do see the other one.


so far, the two places where we see EXC_BAD_ACCESS are unrealted, but reliable.

the first one, is when I try to add an existing object to an array of an existing object. There is notification setup to observe that array, it is never triggered (i have breackpoints and NSLogs on everything right now. I know when the app gets a notification.) the debugger, at the point of adding the object to the array, reports that they both exist.


the second one is a Bool property in a completely different class. Inside that class, I have an Observe metod that sets this Bool to true, we get a EXC_BAD_ACCESS when that is attempted. the debugger, the few times we've been able to get that far reports that the object exists, at the point of it setting it's own property.


So... yes, the same place, but no, not always.


it's possible that in the case of the first error I did something wrong, that I didn't write robust enough code, it's a performDragOperation method for drag n drop, and could have been a little tricky. But I have refactored that thing to only move ahead If each successive line is successful. we couldn't even get to the code that errors out, if everything wasn't essentially working. The only other option is that the array itself have been released. as I said: the debugger says it's there, and I refactored my code to test that it's there. If I comment out that single line... then we won't see the error. If I were to suddenly lose the array before that line... no chance of getting to the line of code. If its' releaed after that line of code, it's too late to affect the outcome we are having.


I am beginning to think it has something to do with the target object, the one that contains the array. But, all tests show it to be there. everything I can know about it indicates that it is intact. And it's not something I change. it is essentially the document object. to get rid of it, would throw many more errors all at once.

last night my code worked. today, it is randomly failing with multiple EXC_BAD_ACESS errors
 
 
Q