Adding a symbolic breakpoint in Xcode gives you an example template of -[NSException raise]. I want to do the same thing but specifically on -[NSRangeException raise]. The reason being that I want to breakpoint only on specific array bounds exceptions, for example:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 31 beyond bounds [0 .. 30]'
Yes, I know that I can add a catch all exception breakpoint. However, I do not want to do that as I do not want to breakpoint on the many exceptions generated throughout using the app.
I've tried quite a few things based on other posts related to NSException. However, I have not found anything that works successfully as yet.
For example I tried:
This journal entry was also of interest albeit inconclusive:
Dealing with NSArray "out of bounds"
So, basically, the question is, in Xcode, how to breakpoint specifically and only on a range exception?
NSRangeException isn't a class:
grep NSRangeException /System/Library/Frameworks/Foundation.framework/Headers/NSException.h
FOUNDATION_EXPORT NSString * const NSRangeException;
Turns out, range exceptions are just NSExceptions whose name is NSRangeException, i.e.:
(lldb) b s -n objc_exception_throw
Breakpoint 2: where = libobjc.A.dylib`objc_exception_throw, address = 0x00007fff8e3c2e4a
(lldb) c
Process 58216 resuming
Process 58216 stopped
* thread #1: tid = 0x1d7f4b, function: objc_exception_throw , stop reason = breakpoint 2.1
frame #0: 0x00007fff8e3c2e4a libobjc.A.dylib`objc_exception_throw
libobjc.A.dylib`objc_exception_throw:
-> 0x7fff8e3c2e4a: pushq %rbp
0x7fff8e3c2e4b: movq %rsp, %rbp
0x7fff8e3c2e4e: pushq %r15
0x7fff8e3c2e50: pushq %r14
(lldb) bt
* thread #1: tid = 0x1d7f4b, function: objc_exception_throw , stop reason = breakpoint 2.1
frame #0: 0x00007fff8e3c2e4a libobjc.A.dylib`objc_exception_throw
frame #1: 0x00007fff841ca1df CoreFoundation`-[__NSArrayI objectAtIndex:]
frame #2: 0x0000000100000eb9 range-exception`-[Foo throwIt] at range-exception.m:14
frame #3: 0x0000000100000f27 range-exception`main at range-exception.m:22
frame #4: 0x00007fff8468d5fd libdyld.dylib`start
frame #5: 0x00007fff8468d5fd libdyld.dylib`start
(lldb) expr (NSString *) [((NSException *) $arg1) name]
(NSString *) $0 = 0x00007fff74177990 #"NSRangeException"
So you could set a breakpoint on objc_exception_throw, and write a breakpoint condition comparing the name to NSRangeException. Something like:
[(NSString *) [((NSException *) $arg1) name] isEqual: (NSString *) NSRangeException]
should do the trick.
To make a breakpoint for NSRangeException, use an Exception breakpoint. It's one of the options when you click the "+" in the breakpoint navigator. Found this info from this answer: https://stackoverflow.com/a/9718552/591487
Related
I'm new to lldb debugging. Recently, I compiled my code and tried to test it. After compilation when I run it, I get 'Bus Error'. So, I thought to use lldb debugger to find out the problem. The terminal gives me output like this:
$ lldb ./testLSTMForwardPass
(lldb) target create "./testLSTMForwardPass"
Current executable set to './testLSTMForwardPass' (x86_64).
(lldb) run
Process 96512 launched: './testLSTMForwardPass' (x86_64)
Testing LSTM Forward pass:
Process 96512 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x102742ba8)
frame #0: 0x0000000102742ba8
-> 0x102742ba8: addb %al, (%rax)
0x102742baa: addb %al, (%rax)
0x102742bac: addb %al, (%rax)
0x102742bae: addb %al, (%rax)
Target 0: (testLSTMForwardPass) stopped.
(lldb) bt all
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x102742ba8)
* frame #0: 0x0000000102742ba8
frame #1: 0x00000001015a1768 libMatrix.so`TMatrixT<double>::operator=(this=0x00007ffeefbfdd60, source=0x0000000102742b60) at TMatrixT.cxx:1739 [opt]
frame #2: 0x00000001015a16e8 libMatrix.so`TMatrixT<double>::TMatrixT(this=0x00007ffeefbfdd60, another=0x0000000102742b60) at TMatrixT.cxx:87 [opt]
frame #3: 0x0000000100006cf0 testLSTMForwardPass`double testForwardPass<TMVA::DNN::TReference<double> >(timeSteps=<unavailable>, batchSize=<unavailable>, stateSize=<unavailable>, inputSize=<unavailable>) at TestLSTMForwardPass.h:98 [opt]
frame #4: 0x000000010000695a testLSTMForwardPass`main at TestLSTMForwardPass.cxx:28 [opt]
frame #5: 0x00007fff65722145 libdyld.dylib`start + 1
frame #6: 0x00007fff65722145 libdyld.dylib`start + 1
I'm not able to understand what this output means. It would be great if anyone can help me to understand it properly. :)
XCode 6 Beta 3 using Swift.
In my App I use CoreData. When I run my App in simulator, XCode pops up the debugger with a breakpoint set somewhere in the CoreData library (see screenshot). This happens on several CoreData functions, for example when inserting new records or fetching records from an entity. The breakpoint position is always the same.
This is extremely annoying. When my App fetches 10 records from an entity I have to push the continue program execution button 10 times.
Because this breakpoint is set somewhere in machine code, the breakpoint inspector does not show any breakpoints so I cannot delete it.
Does anyone know how to get rid of it?
Many thanks.
Edit:
backtrace-output:
(lldb) bt
* thread #1: tid = 0x1d68b0, 0x000000010a2f7fcd libswift_stdlib_core.dylibswift_dynamicCastClassUnconditional + 77, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
* frame #0: 0x000000010a2f7fcd libswift_stdlib_core.dylibswift_dynamicCastClassUnconditional + 77
frame #1: 0x000000010a0fbb85 GPS TrackGPS_Track.TrackListTableViewController.tableView (tableView=<unavailable>)(Swift.ImplicitlyUnwrappedOptional<ObjectiveC.UITableView>, cellForRowAtIndexPath : Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSIndexPath>) -> Swift.Optional<ObjectiveC.UITableViewCell> + 1125 at TrackListTableViewController.swift:53
frame #2: 0x000000010a0fc937 GPS Track#objc GPS_Track.TrackListTableViewController.tableView (GPS_Track.TrackListTableViewController)(Swift.ImplicitlyUnwrappedOptional, cellForRowAtIndexPath : Swift.ImplicitlyUnwrappedOptional) -> Swift.Optional + 87 at TrackListTableViewController.swift:0
frame #3: 0x000000010bc2f218 UIKit-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 508
frame #4: 0x000000010bc0f340 UIKit-[UITableView _updateVisibleCellsNow:isRecursive:] + 2845
frame #5: 0x000000010bc24fea UIKit-[UITableView layoutSubviews] + 213
frame #6: 0x000000010bbb1ebd UIKit-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 519
frame #7: 0x000000010b9c9598 QuartzCore-[CALayer layoutSublayers] + 150
frame #8: 0x000000010b9be1be QuartzCoreCA::Layer::layout_if_needed(CA::Transaction*) + 380
frame #9: 0x000000010b9be02e QuartzCoreCA::Layer::layout_and_display_if_needed(CA::Transaction*) + 24
frame #10: 0x000000010b92cf16 QuartzCoreCA::Context::commit_transaction(CA::Transaction*) + 242
frame #11: 0x000000010b92e022 QuartzCoreCA::Transaction::commit() + 390
frame #12: 0x000000010b92e68d QuartzCoreCA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 89
frame #13: 0x000000010ab52927 CoreFoundation__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
frame #14: 0x000000010ab52880 CoreFoundation__CFRunLoopDoObservers + 368
frame #15: 0x000000010ab480d3 CoreFoundation__CFRunLoopRun + 1123
frame #16: 0x000000010ab47a06 CoreFoundationCFRunLoopRunSpecific + 470
frame #17: 0x000000010e9e9abf GraphicsServicesGSEventRunModal + 161
frame #18: 0x000000010bb39cf8 UIKitUIApplicationMain + 1282
frame #19: 0x000000010a0e6a5d GPS Tracktop_level_code + 77 at AppDelegate.swift:36
frame #20: 0x000000010a0e6a9a GPS Trackmain + 42 at AppDelegate.swift:0
frame #21: 0x000000010d2e7145 libdyld.dylib`start + 1
(lldb)
I tracked it down further: The problem only occurs when using custom object classes for the entities. Example:
// User class, defined in User.swift
class User: NSManagedObject {
#NSManaged var name: String
#NSManaged var firstname: String
}
// --------------
// code somewhere else
let users = moc.executeFetchRequest(fetchRequest, error: &error)
for object in users {
let user = object as User // <-- breakpoint fired here
println(user.name)
}
}
SOLUTION:
One need to make the custom object class visible to Objective C using the #objc directive:
// User class, defined in User.swift
#objc(User) // <-- required!
class User: NSManagedObject {
#NSManaged var name: String
#NSManaged var firstname: String
}
Thanks to all for your help!
Do you have an All Exception breakpoint set?
Contrary to Apple's best practices CoreData uses exceptions in the normal flow of control.
If you add exception breakpoints you may break in CoreData. The solution is to remove or disable the exception breakpoint.
While the above answers all are technically correct
#zisoft is right, however if you're using custom NSManagedObject classes then you should always use #objc(User), not just because of this break point.
#Zaph may work also, as you're essentially not listening and if indeed it's a bug it should stop it from appearing
However you may still hit this kind of break point if you're not type checking. I suspect it's a breakpoint in the beta 4 but will become a crash in the next beta.
I solved the issue in my code as I was hitting on returning the managed object received from insertNewObjectForEntityForName as AnyObject and later saying as myclass when I used it. Fine as I knew it was my class. but actualy should have done something like this
func createMyEntity() -> MyClass{
if let entity : MyClass = NSEntityDescription.insertNewObjectForEntityForName("MyClass", inManagedObjectContext: self.managedObjectContext) as? MyClass
{
return entity;
}
return nil;
}
Obviously that's just one example, but if you're the hitting the break point in other places then hopefully this a good reference.
Not withstanding this still may just be a bug in beta 4 of xcode, but this is safer anyway.
Update -- It also checking that your data model class name matches as it later through a warning here an this may also be why the breakpoint was hit.
I fixed my version of this problem based on info in https://devforums.apple.com/message/1016337#1016337
make the NSManagedObject-derived class and its relevant properties public
do not include its source file in the test target's Compile Sources
import the app target in the test file -- e.g., import MyApp in MyClassTests.swift
In your Core Data *.xcdatamodeld file, prefix your entity's class name with your app name. It should look something like this when you're done:
Thanks the last helped!!!
make the NSManagedObject-derived class and its relevant properties public
do not include its source file in the test target's Compile Sources
import the app target in the test file -- e.g., import MyApp in MyClassTests.swift
Following helped me !
If I undone one of this settings the breakpoint error comes again !
You have to set for your Entity-Model in your *Model.xcdatamodeld in property "Class" the same Name example: Name=Chat Class=Chat
You have to add Code #objc(yourClass) above your class
Pictures 1:
http://i.stack.imgur.com/xoxtu.png
Pictures 2:
http://i.stack.imgur.com/LkYYq.png
For anyone using Xcode 6.2
Make #objc changes to your class i.e #objc(className)
Next go to *.xcdatamodeld -> Configurations (Default if nothing specified) -> add class against entity
First of all a bit of context: I'm trying to debug an issue that's happening with neovim, I'm not sure if this also happens with plain vim, but it's not all that relevant.
Even though the reporter uses linux and I use OSX 10.9, I've been able to get "similar" behaviour by using specific compilers + flags:
When I use either gcc 4.8.2 or gcc 4.9 (dev) combined with even a little bit of optimization, fortification and stack smashing protection, neovim crashes on startup.
$ edit CMakeLists.txt
$ ... -Wall -O1 -g -g3 -ggdb -mtune=generic -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -Wextra -pedantic -Wno-unused-parameter -std=gnu99 ...
$ make clean && make cmake CMAKE_EXTRA_FLAGS="-DCMAKE_C_COMPILER=/usr/local/bin/gcc-4.8" && make
I've been trying to debug it with lldb (gdb doesn't seem to give my any symbols, even after codesigning). I've gotten as far as this:
compiled with gcc 4.9:
➜ neovim git:(fortify-and-stack-protector) ✗ lldb ./build/bin/nvim
Current executable set to './build/bin/nvim' (x86_64).
(lldb) run src/eval.c
Process 1295 launched: './build/bin/nvim' (x86_64)
Process 1295 stopped
* thread #1: tid = 0x242b4f, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff93f34866: jae 0x7fff93f34870 ; __pthread_kill + 20
0x7fff93f34868: movq %rax, %rdi
0x7fff93f3486b: jmpq 0x7fff93f31175 ; cerror_nocancel
0x7fff93f34870: ret
(lldb) bt
* thread #1: tid = 0x242b4f, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff91b6435c libsystem_pthread.dylib`pthread_kill + 92
frame #2: 0x00007fff8ce68b1a libsystem_c.dylib`abort + 125
frame #3: 0x00007fff8ce68c91 libsystem_c.dylib`abort_report_np + 181
frame #4: 0x00007fff8ce8c860 libsystem_c.dylib`__chk_fail + 48
frame #5: 0x00007fff8ce8c830 libsystem_c.dylib`__chk_fail_overflow + 16
frame #6: 0x00007fff8ce8ca7f libsystem_c.dylib`__strcpy_chk + 83
frame #7: 0x000000010002e1a6 nvim`call_user_func [inlined] add_nr_var(nr=1, name=<unavailable>, v=<unavailable>, dp=<unavailable>) + 42 at eval.c:18744
frame #8: 0x000000010002e17c nvim`call_user_func(fp=0x000000010030bd30, argcount=0, argvars=0x00007fff5fbfed80, rettv=0x00007fff5fbfef50, firstline=1, lastline=1, selfdict=0x0000000000000000) + 425 at eval.c:18455
frame #9: 0x000000010002ef33 nvim`call_func(funcname=<unavailable>, len=<unavailable>, rettv=0x00007fff5fbfef50, argcount=0, argvars=0x00007fff5fbfed80, firstline=1, lastline=1, doesrange=0x00007fff5fbfef44, evaluate=1, selfdict=0x0000000000000000) + 717 at eval.c:7363
frame #10: 0x0000000100032d1a nvim`get_func_tv(name=0x000000010030be20, len=9, rettv=0x00007fff5fbfef50, arg=0x00007fff5fbfef48, firstline=1, lastline=1, doesrange=0x00007fff5fbfef44, evaluate=1, selfdict=0x0000000000000000) + 340 at eval.c:7222
frame #11: 0x000000010003673e nvim`ex_call(eap=0x00007fff5fbff190) + 475 at eval.c:3086
frame #12: 0x000000010005634b nvim`do_cmdline(cmdline=<unavailable>, fgetline=0x00000001000494e3, cookie=0x00007fff5fbff790, flags=7) + 13602 at ex_docmd.c:2103
frame #13: 0x0000000100049d52 nvim`do_source(fname=0x000000010017bb3b, check_other=<unavailable>, is_vimrc=<unavailable>) + 1615 at ex_cmds2.c:2695
frame #14: 0x00000001001702c3 nvim`main + 251 at main.c:2009
frame #15: 0x00000001001701c8 nvim`main(argc=<unavailable>, argv=<unavailable>) + 5152 at main.c:1919
frame #16: 0x00007fff8b32d5fd libdyld.dylib`start + 1
(lldb) frame variable
(lldb) frame info
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
(lldb) frame select 7
frame #7: 0x000000010002e1a6 nvim`call_user_func [inlined] add_nr_var(nr=1, name=<unavailable>, v=<unavailable>, dp=<unavailable>) + 42 at eval.c:18744
18741 */
18742 static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr)
18743 {
-> 18744 STRCPY(v->di_key, name);
18745 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18746 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
18747 v->di_tv.v_type = VAR_NUMBER;
compiled with gcc 4.8.2:
➜ neovim git:(fortify-and-stack-protector) ✗ lldb ./build/bin/nvim
Current executable set to './build/bin/nvim' (x86_64).
(lldb) rune
error: 'rune' is not a valid command.
(lldb) run
Process 3242 launched: './build/bin/nvim' (x86_64)
Process 3242 stopped
* thread #1: tid = 0x2454cb, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff93f34866: jae 0x7fff93f34870 ; __pthread_kill + 20
0x7fff93f34868: movq %rax, %rdi
0x7fff93f3486b: jmpq 0x7fff93f31175 ; cerror_nocancel
0x7fff93f34870: ret
(lldb) bt
* thread #1: tid = 0x2454cb, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff91b6435c libsystem_pthread.dylib`pthread_kill + 92
frame #2: 0x00007fff8ce68b1a libsystem_c.dylib`abort + 125
frame #3: 0x00007fff8ce68c91 libsystem_c.dylib`abort_report_np + 181
frame #4: 0x00007fff8ce8c860 libsystem_c.dylib`__chk_fail + 48
frame #5: 0x00007fff8ce8c830 libsystem_c.dylib`__chk_fail_overflow + 16
frame #6: 0x00007fff8ce8ca7f libsystem_c.dylib`__strcpy_chk + 83
frame #7: 0x000000010002a969 nvim`eval_init + 129 at eval.c:868
frame #8: 0x0000000100089ffd nvim`main(argc=1, argv=0x00007fff5fbffa58) + 140 at main.c:175
frame #9: 0x00007fff8b32d5fd libdyld.dylib`start + 1
frame #10: 0x00007fff8b32d5fd libdyld.dylib`start + 1
(lldb) frame select 7
frame #7: 0x000000010002a969 nvim`eval_init + 129 at eval.c:868
865
866 for (i = 0; i < VV_LEN; ++i) {
867 p = &vimvars[i];
-> 868 STRCPY(p->vv_di.di_key, p->vv_name);
869 if (p->vv_flags & VV_RO)
870 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
871 else if (p->vv_flags & VV_RO_SBX)
For this issue to appear, there needs to be some optimization, however this means that the compiler will inline things and throw away arguments, which is annoying and doesn't allow me to see the most important things at a glance. Would there be a combination of flags I could try that would keep the problem but allow better debuggability?
Is this likely a compiler bug? Clang seems to avoid it somehow, and GCC too when I turn off optimization.
gcc 4.8.2 and gcc 4.9 give a similar error (both times at a STRCPY) but in different locations, this worries me even more.
Where is the code for __chk_fail_overflow and __chk_overlap? They get called in strcpy_chk which I assume is the replacement of strcpy that gets inserted when compiling with -D_FORTIFY_SOURCE=2. I haven't been able to grep for it. I've grepped in this repo: https://github.com/aosm/Libc which appears to be the OSX 10.9 libc as I've tried to verify with apple's own opensource site.
How does the compiler decide what the 3rd argument to strcpy_chk is?! The original invocation to STRCPY doesn't include any size information:
.
STRCPY(v->di_key, name);
// I think gcc/clang replace this with:
__strcpy_chk(v->di_key, name, SOME_MAGIC_SIZE);
I hope some of the guru's on stack overflow could give me some tips/hints on what I should do next!
EDIT: I've been able to compile with -Og and gcc 4.8.2 and still provoke the error, hopefully this will give some more info.
So, I couldn't stop myself from digging further and finally got the idea of looking at the stack + registers when entereing the dreaded __strcpy_chk, where I found:
(lldb) register read
General Purpose Registers:
rax = 0x0000000000000057
rbx = 0x00000001001d3900 vimvars
rcx = 0x6300f1e7a96add52
rdx = 0x0000000000000001 /* this is probably the size parameter */
rdi = 0x00000001001d3919 vimvars + 25
rsi = 0x000000010016730e "count"
So gcc had deduced that the size of the dst parameter was 1, and is passing that to __strcpy_chk. So, because of the -D_FORTIFY_SOURCE=2, gcc replaces calls of well-known functions with their safe variants when it can deduce the size. Such is the case here as we'll see: the dst parameter is the vv_di.di_key field of this struct:
static struct vimvar {
char *vv_name; /* name of variable, without v: */
dictitem_T vv_di; /* value and name for key */
char vv_filler[16]; /* space for LONGEST name below!!! */
char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
}
struct dictitem_S {
typval_T di_tv; /* type and value of the variable */
char_u di_flags; /* flags (only used for variable) */
char_u di_key[1]; /* key (actually longer!) */
}
Which has size 1. Gcc of course doesn't realize that this was somehow intentional: the vv_filler flag is meant to store the actual string. Which is why the comment says actually longer. vv_filler follows immediately on di_key in the struct.
I can't really fault the compiler for this, it makes sense. Someone at the neovim project is busy rebuilding the interpreter to be a translator from VimL to lua. A "stupid" fix at the moment is to either disable source fortifying or lower it a level to -D_FORTIFY_SOURCE=1, which should stop gcc from making these assumptions. Ideally though, we'd be able to fix this while keeping -D_FORTIFY_SOURCE=2 and not regressing in performance (vimvar is of course an oft-used struct).
I have some extra questions though. Is what the vim codebase does here legal? There were some discussions on the neovim issue tracker where some commenters suggested that relying on this was entirely undefined. One argument that I found interesting was that there could be space between the end of struct dictitem_S and vv_filler (padding). The commenter argued that it was illegal (UB) to use this space. Reading the relevant C99 documents doesn't provide immediate clarity on this specific case. The struct hack is allowed, but we were not sure if it is allowed for nested structs. i.e.: the struct hack appears at the end of dictitem_S, but definitely not at the end of its containing struct (vimvar).
This is my first post. I apologize for mistakes.
I have a crash I can fix, but I don't understand why it crashes in the first place. I tried to reduce the code to the essentials to make it crash:
GCFTile *currentTile;
NSInteger repeatCount = 0;
do {
currentTile = self.remainingTilesArray[0];
if (repeatCount == 0) {
[self.remainingTilesArray removeObjectAtIndex:0];
[self.remainingTilesArray addObject:currentTile];
}
void (^myBlock)() = ^{
currentTile;
};
repeatCount++;
} while (repeatCount == 1);
I'm using Xcode 4.5.2, iOS 5, ARC. Also, it crashes only if the LLVM compiler optimization is set to "Fast" or above.
The code above will get and remove an object from an NSMutableArray, put it back, and then get another object from the array. The code above will run without crashing, but if I scan across all the elements in the array later (e.g., from a different method), then it crashes. It looks like a random memory address was added to the array (probably from the above call to addObject).
The above block should do nothing, but if I change it then there's no crash later. (E.g., empty block = no crash. Don't declare block as "myBlock" = no crash.) If I don't repeat the loop, there's no crash. If I don't add the object back, there's no crash. If I declare currentTile using __block or within the do loop, there's no crash.
I know blocks are "stack-local," but this block doesn't do anything! And it runs fine without compiler optimization.
Any idea what's going on?
EDIT (12-5-12): Someone asked for the crash log. I'm running in the simulator, so I don't know how to get that. But here's a little from the Debug Navigator:
#0 0x0140409b in objc_msgSend ()
#1 0x00010931 in __33-[GCFGame checkThatTilesAreValid]_block_invoke_0 at /Users/geoffrey2/personal/projects/Color Fever/Color Fever/GCFGame.m:54
#2 0x01cb24a5 in __NSArrayEnumerate ()
#3 0x01cb2026 in -[NSArray enumerateObjectsWithOptions:usingBlock:] ()
#4 0x01cb1f35 in -[NSArray enumerateObjectsUsingBlock:] ()
#5 0x000108f6 in -[GCFGame checkThatTilesAreValid] at /Users/geoffrey2/personal/projects/Color Fever/Color Fever/GCFGame.m:52
and the main window shows this (plus more lines):
libobjc.A.dylib`objc_msgSend:
0x140408c: movl 8(%esp), %ecx
0x1404090: movl 4(%esp), %eax
0x1404094: testl %eax, %eax
0x1404096: je 0x14040e8 ; objc_msgSend + 92
0x1404098: movl (%eax), %edx
0x140409a: pushl %edi
0x140409b: movl 8(%edx), %edi
The error is EXC_BAD_ACCESS(code=2, adddress=0x9).
My app is crashing with this error message:
'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: 0)'
and I am trying to find where this is occuring in my code. I have set NSZombiesEnabled in the environment variables, however it's pretty hard to figure out the location. Any idea on how to debug?
I typed in bt and here's what I see:
frame #0: 0x30d1832c libsystem_kernel.dylib`__pthread_kill + 8
frame #1: 0x3597d20e libsystem_c.dylib`pthread_kill + 54
frame #2: 0x3597629e libsystem_c.dylib`abort + 94
frame #3: 0x35055f6a libc++abi.dylib`abort_message + 46
frame #4: 0x3505334c libc++abi.dylib`_ZL17default_terminatev + 24
frame #5: 0x36c38356 libobjc.A.dylib`_objc_terminate + 146
frame #6: 0x350533c4 libc++abi.dylib`_ZL19safe_handler_callerPFvvE + 76
frame #7: 0x35053450 libc++abi.dylib`std::terminate() + 20
frame #8: 0x35054824 libc++abi.dylib`__cxa_rethrow + 88
frame #9: 0x36c382a8 libobjc.A.dylib`objc_exception_rethrow + 12
frame #10: 0x3428d50c CoreFoundation`CFRunLoopRunSpecific + 404
frame #11: 0x3428d36c CoreFoundation`CFRunLoopRunInMode + 104
frame #12: 0x3826f438 GraphicsServices`GSEventRunModal + 136
frame #13: 0x36d27cd4 UIKit`UIApplicationMain + 1080
frame #14: 0x00051cdc AppName`main + 80 at main.m:16
Add exceptions as a breakpoint. Assuming Xcode 4+...
At the top of the navigator frame (where you view files and such), you will see a little icon that looks like a sideways arrow.
That will show the breakpoint navigator. At the bottom of that view, click the + to add a breakpoint.
Click on "Add exception breakpoint..."
The default option is probably fine... you want to break on throw of all exceptions.
Now, when you run, you will get a breakpoint anywhere your app throws an exception.
Is the error happening in your testing? Are you seeing it from crash logs from iTunes Connect?
If you are able to reproduce it locally, run the scenario to duplicate the error and when the debugger becomes active, type "bt" at the (gdb) prompt in the Console for a stacktrace with a line number.
Try to add this part of code in your AppDelegate :
void uncaughtExceptionHandler(NSException *exception);
void uncaughtExceptionHandler(NSException *exception) {
NSLog(#"CRASH: %#", exception);
NSLog(#"Stack Trace: %#", [exception callStackSymbols]);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// your previous code here
return YES;
}
Next time your error occurs, you should have some additional infos on the crash.