Not getting output in first Y86 program - y86

I'm trying to learn Y86, so I made a very simple program. It has an array of three long integers, and each block is filled by asking the user for an input through rdint.
The compiled(?) program asks for three inputs, but is not able to print them out.
Code:
Main: irmovl Array, %edx
rdint %eax
rmmovl %eax, 0(%edx)
rdint %eax
rmmovl %eax, 4(%edx)
rdint %eax
rmmovl %eax, 8(%edx)
irmovl $10, %edi
Print: irmovl Array, %edx
mrmovl 0(%edx), %eax
wrch %eax
wrch %edi
mrmovl 4(%edx), %eax
wrch %eax
wrch %edi
mrmovl 8(%edx), %eax
wrch %eax
wrch %edi
halt
.align 4
Array:
.long 0
.long 0
.long 0
My input:
0
1
2
Output:
(three blank lines below)
Stopped in 22 steps at PC = 0x47. Exception 'HLT', CC Z=1 S=0 O=0
Changes to registers:
%edx: 0x00000000 0x0000004c
%edi: 0x00000000 0x0000000a
Changes to memory:
0x0004: 0x024008f2 0x00000001
0x0008: 0x00000000 0x00000002
Changes to memory: 0x0004: 0x024008f2 0x00000001 0x0008:
0x00000000 0x00000002

There is a classic problem with the program: Lack of new-line in the ys file, causing YAS to misbehave.
The first problem is due to an error in YAS. If you look in the yo file produced by YAS you will see that the last .long 0 statement never gets defined. You will probably also see that the first line opcode in the yo file is 0x00, i.e. nop (when YAS encounter a final instruction without an associated newline, it wraps it around, screwing up the yo file)
This means that you loose the first irmovl Array, %edx (it becomes some sort of nonsense, probably 0x00000000, i.e. 4 nops,) and so you write the first read character x'30' (ascii for '0') to the location pointd to by edx (which is probably 0x00000000,) is in the first instruction (which was 4 nops -- remember that you read a character, but it ends up in a 4 byte register and is saved as such.) So you are writing 0x00000000 to and address that was 0x00000000, which to YIS means that the register was not changed and therefore it is not shown in the "Changes to Memory" dump section.
You repeat this with the second read, writing 0x00000001 in the second word (overwriting the instruction in that location,) and with the third read, writing 0x00000002 in the third word (overwriting the instruction in that location.)
Now, of course, you are completely hosed! You reset the pointer to the array (using edx,) and attempt to print the content, but Array(0), Array(4), and Array(8) contains 0x00000000, because that is what you defined it as (using your .long 4 statements for Array(0) and Array(4) and automatically for Array(8) since the default set-up for undefined memory in Y86 is 0x00000000. And so, the program prints x'00' (because you print one character from a 4 byte word,) which, of course, is junk.
You will note that this fits with the dump from YIS. eax does not show as it is unchanged from 0x00000000, its initial value. edx and edi look A-OK, with edi pointing to Array(8). The only memory that has changed is the second and third word of the program (which have been overwritten with 0x00000001 and 0x00000002, respectively)
So, in summary. YAS makes a mistake. You must overcome this problem by adding a new-line after the last .long 0 statement. YIS misleads you because, critically!, it does not throw exceptions when you overwrite code with data.

Related

why did not fill with zeros

Allocated array for 10000 bits = 1250 bytes(10000/8):
mov edi, 1250
call malloc
tested the pointer:
cmp rax, 0
jz .error ; error handling at label down the code
memory was allocated:
(gdb) p/x $rax
$3 = 0x6030c0
attempted to fill that allocated memory with zeros:
mov rdi, rax
xor esi, esi
mov edx, 1250 ; 10000 bits
call memset
checked first byte:
(gdb) p/x $rax
$2 = 0x6030c0
(gdb) x/xg $rax + 0
0x6030c0: 0x0000000000000000
checked last byte(0 - first byte, 1249 - last byte)
(gdb) p/x $rax + 1249
$3 = 0x6035a1
(gdb) x/xg $rax + 1249
0x6035a1: 0x6100000000000000
SOLVED QUESTION
Should have typed x/1c $rax + 1249
You interpreted memory as a 64 bit integer, but you forgot that endianness of intel is little endian. So bytes were reversed.
0x6100000000000000 is the value that the CPU reads when de-serializing the memory at this address. Since it's little endian, the 0x61 byte is last in memory (not very convenient to dump memory in this format, unless you have a big endian architecture)
Use x /10bx $rax + 1249 you'll see that it's zero at the correct location. The rest is garbage (happens to be zero for a while, then garbage)
0x00 0x00 0x00 0x00 0x00 0x00 0x61

Getting bit-pattern of bool in Swift

In ObjC, a bool's bit pattern could be retrieved by casting it to a UInt8.
e.g.
true => 0x01
false => 0x00
This bit pattern could then be used in further bit manipulation operations.
Now I want to do the same in Swift.
What I got working so far is
UInt8(UInt(boolValue))
but this doesn't look like it is the preferred approach.
I also need the conversion in O(1) without data-dependent branching. So, stuff like the following is not allowed.
boolValue ? 1 : 0
Also, is there some documentation about the way the UInt8 and UInt initializers are implemented? e.g. if the UInt initializer to convert from bool uses data-dependent branching, I can't use it either.
Of course, the fallback is always to use further bitwise operations to avoid the bool value altogether (e.g. Check if a number is non zero using bitwise operators in C).
Does Swift offer an elegant way to access the bit pattern of a Bool / convert it to UInt8, in O(1) without data-dependent branching?
When in doubt, have a look at the generated assembly code :)
func foo(someBool : Bool) -> UInt8 {
let x = UInt8(UInt(someBool))
return x
}
compiled with ("-O" = "Compile with optimizations")
xcrun -sdk macosx swiftc -emit-assembly -O main.swift
gives
.globl __TF4main3fooFSbVSs5UInt8
.align 4, 0x90
__TF4main3fooFSbVSs5UInt8:
.cfi_startproc
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
callq __TFE10FoundationSb19_bridgeToObjectiveCfSbFT_CSo8NSNumber
movq %rax, %rdi
callq __TFE10FoundationSuCfMSuFCSo8NSNumberSu
movzbl %al, %ecx
cmpq %rcx, %rax
jne LBB0_2
popq %rbp
retq
The function names can be demangled with
$ xcrun -sdk macosx swift-demangle __TFE10FoundationSb19_bridgeToObjectiveCfSbFT_CSo8NSNumber __TFE10FoundationSuCfMSuFCSo8NSNumberSu
_TFE10FoundationSb19_bridgeToObjectiveCfSbFT_CSo8NSNumber ---> ext.Foundation.Swift.Bool._bridgeToObjectiveC (Swift.Bool)() -> ObjectiveC.NSNumber
_TFE10FoundationSuCfMSuFCSo8NSNumberSu ---> ext.Foundation.Swift.UInt.init (Swift.UInt.Type)(ObjectiveC.NSNumber) -> Swift.UInt
There is no UInt initializer that takes a Bool argument.
So the smart compiler has used the automatic conversion between Swift
and Foundation types and generated some code like
let x = UInt8(NSNumber(bool: someBool).unsignedLongValue)
Probably not very efficient with two function calls. (And it does not
compile if you only import Swift, without Foundation.)
Now the other method where you assumed data-dependent branching:
func bar(someBool : Bool) -> UInt8 {
let x = UInt8(someBool ? 1 : 0)
return x
}
The assembly code is
.globl __TF4main3barFSbVSs5UInt8
.align 4, 0x90
__TF4main3barFSbVSs5UInt8:
pushq %rbp
movq %rsp, %rbp
andb $1, %dil
movb %dil, %al
popq %rbp
retq
No branching, just an "AND" operation with 0x01!
Therefore I do not see a reason not to use this "straight-forward" conversion.
You can then profile with Instruments to check if it is a bottleneck for
your app.
#martin-r’s answer is more fun :-), but this can be done in a playground.
// first check this is true or you’ll be sorry...
sizeof(Bool) == sizeof(UInt8)
let t = unsafeBitCast(true, UInt8.self) // = 1
let f = unsafeBitCast(false, UInt8.self) // = 0

Anyone use CFAllocatorSetDefault succesfully in an iPhone app?

I wish to replace the default CFAllocator in my iPhone app with my own implementation. I want to control the memory allocated by the UIWebView since it seems to hold on to so much memory after loading a website and that memory still lingers around when the UIWebView is released.
After I call CFAllocatorSetDefault I get an EXC_BREAKPOINT exception when the next allocation occurs.
The exception seems to happen inside of a call to CFRetain (done in the simulator but the same thing happens on a device):
CoreFoundation`CFRetain:
0x1c089b0: pushl %ebp
0x1c089b1: movl %esp, %ebp
0x1c089b3: pushl %edi
0x1c089b4: pushl %esi
0x1c089b5: subl $16, %esp
0x1c089b8: calll 0x1c089bd ; CFRetain + 13
0x1c089bd: popl %edi
0x1c089be: movl 8(%ebp), %esi
0x1c089c1: testl %esi, %esi
0x1c089c3: jne 0x1c089db ; CFRetain + 43
0x1c089c5: int3
0x1c089c6: calll 0x1d66a00 ; symbol stub for: getpid <- EXC_BREAKPOINT (code=EXC_I386_BPT subcode=0x0)
0x1c089cb: movl %eax, (%esp)
0x1c089ce: movl $9, 4(%esp)
0x1c089d6: calll 0x1d66a4e ; symbol stub for: kill
0x1c089db: movl (%esi), %eax
0x1c089dd: testl %eax, %eax
0x1c089df: je 0x1c08a17 ; CFRetain + 103
0x1c089e1: cmpl 1838519(%edi), %eax
0x1c089e7: je 0x1c08a17 ; CFRetain + 103
0x1c089e9: movl 4(%esi), %ecx
0x1c089ec: shrl $8, %ecx
0x1c089ef: andl $1023, %ecx
0x1c089f5: cmpl 1834423(%edi,%ecx,4), %eax
0x1c089fc: je 0x1c08a17 ; CFRetain + 103
0x1c089fe: movl 1766575(%edi), %eax
0x1c08a04: movl %eax, 4(%esp)
0x1c08a08: movl %esi, (%esp)
0x1c08a0b: calll 0x1d665c8 ; symbol stub for: objc_msgSend
UPDATE
Core Foundation has a bug that makes CFAllocatorSetDefault useless.
Specifically, if you study the implementation of _CFRuntimeCreateInstance in CFRuntime.c, you'll see that:
If it's not using the system default allocator, it tries to retain the allocator.
If it's been passed NULL as its allocator argument, it will try to retain that NULL instead of the current default allocator.
The call to CFRetain will therefore crash.
What it should do is retain the current default allocator when it's given NULL as its allocator argument.
Since lots of functions in Apple's own libraries apparently pass NULL (or kCFAllocatorDefault, which is also a null pointer) to functions that create a Core Foundation object, you're bound to crash quickly if you change the default allocator at all.
My test case: I created a new, single-view iPhone app. I added one line to main:
int main(int argc, char *argv[])
{
CFAllocatorSetDefault(kCFAllocatorMalloc);
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
The app crashes during startup on the simulator and on my test device, in CFRetain, with EXC_BREAKPOINT, with a null pointer as the function argument.
ORIGINAL
You are passing a null pointer to CFRetain. If this has anything to do with your custom allocator, you need to post more details, like the full call stack when the exception occurs.
In your disassembly listing, the instructions from 0x1c089b0 through 0x1c089bd are the function prologue.
At 0x1c089be, the movl 8(%ebp), %esi instruction loads the first function argument from the stack into %esi.
At 0x1c089c1, the testl %esi, %esi instruction sets the processor flags based on the value of %esi. In particular, it sets the Z (zero) flag to 1 if %esi contains zero, and sets the Z flag to 0 if %esi contains anything else.
At 0x1c089c3, the jne 0x1c089db instruction jumps if the ne condition is true. The ne condition is true when the Z flag is 0 and false when the Z flag is 1. So this instruction jumps when %esi (the first argument) is non-zero, and falls through when %esi is zero.
At 0x1c089c5, the int3 instruction raises a SIGTRAP signal with exception code EXC_BREAKPOINT. The int3 instruction is normally stuffed into a program by the debugger when you set a breakpoint. In this case, it was hardcoded in the program at compile-time.
Thus, you are getting this exception because you are passing a null pointer to CFRetain.
You can also look at the source code of CFRetain if you like. It is in CFRuntime.c:
CFTypeRef CFRetain(CFTypeRef cf) {
if (NULL == cf) { CRSetCrashLogMessage("*** CFRetain() called with NULL ***"); HALT; }
if (cf) __CFGenericAssertIsCF(cf);
return _CFRetain(cf, false);
}
So the very first thing CFRetain does is test whether its argument is NULL. CGSetCrashLogMessage is a macro defined in CoreFoundation_Prefix.h that does nothing. HALT is a macro defined in CFInternal.h:
#define HALT do {asm __volatile__("int3"); kill(getpid(), 9); } while (0)
As you can see, HALT has a hard-coded int3 instruction. Then it calls kill(getpid(), 9). This matches your disassembly listing.

Error syscall : Function not implemented

I'm trying to add new (dummy) system call to linux kernel.
1) I added the system call code under linux-source/kernel/myfile.c and updated the Makefile accordingly.
2) Updated syscall.h, unistd.h and entry.S files to reflect the new system call (pedagogictime(int flag,struct timeval *time))
Then compiled the kernel and installed and rebooted the image.
When I run: cat /proc/kallsyms | grep "pedag", this is the output I'm getting
0000000000000000 T sys_pedagogictime
0000000000000000 d event_exit__pedagogictime
0000000000000000 d event_enter__pedagogictime
0000000000000000 d __syscall_meta_pedagogictime
0000000000000000 d types_pedagogictime
0000000000000000 d args__pedagogictime
0000000000000000 t trace_init_flags_enter__pedagogictime
0000000000000000 t trace_init_flags_exit__pedagogictime
0000000000000000 t __event_exit__pedagogictime
0000000000000000 t __event_enter__pedagogictime
0000000000000000 t __p_syscall_meta__pedagogictime
0000000000000000 t __initcall_trace_init_flags_exit__pedagogictimeearly
0000000000000000 t __initcall_trace_init_flags_enter__pedagogictimeearly
which means the system call is registered correctly.
In my user space program, I'm writing:
#define __NR_pedagogictime 1326 //1326 is my system call number
struct timeval *now = (struct timeval *)malloc(sizeof(struct timeval));
long ret = syscall(__NR_pedagogictime,0,now);
if(ret)
perror("syscall ");
But I'm getting the error:
"syscall : Function not implemented"
I would really appreciate any help about this. Thanks.
Edit:
Btw, the assembly code for the syscall() looks like this (if it helps):
movl $6, %esi
movl $1326, %edi
movl $0, %eax
call syscall
cltq
You've chosen the wrong syscall number. Take a look at how the kernel checks the syscall number limits here. For example (x86, 32bit):
496 ENTRY(system_call)
497 RING0_INT_FRAME # can't unwind into user space anyway
498 pushl_cfi %eax # save orig_eax
499 SAVE_ALL
500 GET_THREAD_INFO(%ebp)
501 # system call tracing in operation / emulation
502 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
503 jnz syscall_trace_entry
504 cmpl $(nr_syscalls), %eax
505 jae syscall_badsys
506 syscall_call:
507 call *sys_call_table(,%eax,4)
508 movl %eax,PT_EAX(%esp) # store the return value
So, you can see that this code compares %eax (syscall number) and nr_syscalls (sys_call_table size). Above or equal leads to syscall_badsys.
You'll need to modify the arch/x86/include/asm/unistd_32.h header too.

-[ClassRoster controllerWillChangeContent:]: message sent to deallocated instance

I know these errors are very app-specific and almost always due to over-releasing an object. I just can't spot it and the debugging tips I have read haven't done the trick for me yet.
According to this debugging advice, my "offending object" was allocated in this code block (located in AddClass.m):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 1) {
ClassRoster *classRoster = [[ClassRoster alloc] init];
classRoster.managedObjectContext = managedObjectContext;
classRoster.newClass = self.newClass;
classRoster.title = #"Class Roster";
[self.navigationController pushViewController:classRoster animated:YES];
[classRoster release];
}
}
However, I don't understand how the offending object could be from here. I believe I am appropriately releasing classRoster and nothing else is being allocated.
The error message clearly indicates that the program was trying to update an object in my classRoster TableViewController. This makes sense, because the crash occurred as I was trying to save an object in classRoster's detailViewController (AddStudent.m) that gets pushed on when an object in classRoster is selected.
To give the broader context of this problem, I am using Core Data and (as you can see from the above code) passing a single managedObjectContextbetween views in order to edit and save a list of classes and their related class rosters. I am using [managedObjectContext rollback] to cancel changes.
It might be worth mentioning that the save method inside of AddStudent.m updates the newly-created student object with strings entered by the user and then adds that student object to its parent class object via [class addStudentObject:student]. The detailViewController (AddStudent.m) is then popped with [delegate addStudent:self didFinishWithSave:YES]. Upon returning to ClassRoster.m, the managedObjectContext is saved.
If you think my Core Data management might be the problem, just let me know what code you would like to see. This is my first app and consequently I have the joy of making lots of stupid mistakes!
UPDATE:
I have honed in on the sequence of actions that results in a crash. I will always crash with the error in my question's subject line if I do the following:
Select an existing class object (push on its AddClass detailViewController)
Select to view the class' roster
Hit the back button to return to the class object detailView
Select to view the class' roster again
Select to add new student or select an existing student object
Choose to save
The break line is marked by "BREAK >>" in the following stack trace:
0x01e8c2f0 <+0000> push %ebp
0x01e8c2f1 <+0001> mov %esp,%ebp
0x01e8c2f3 <+0003> push %edi
0x01e8c2f4 <+0004> push %esi
0x01e8c2f5 <+0005> push %ebx
0x01e8c2f6 <+0006> sub $0x5c,%esp
0x01e8c2f9 <+0009> call 0x1e8c2fe <___forwarding___+14>
0x01e8c2fe <+0014> pop %ebx
0x01e8c2ff <+0015> mov 0xc(%ebp),%esi
0x01e8c302 <+0018> test %esi,%esi
0x01e8c304 <+0020> je 0x1e8c620 <___forwarding___+816>
0x01e8c30a <+0026> mov 0x8(%ebp),%eax
0x01e8c30d <+0029> add $0x4,%eax
0x01e8c310 <+0032> mov 0x8(%ebp),%edx
0x01e8c313 <+0035> mov 0x4(%edx),%edx
0x01e8c316 <+0038> mov %edx,-0x30(%ebp)
0x01e8c319 <+0041> mov 0x4(%eax),%eax
0x01e8c31c <+0044> mov %eax,-0x2c(%ebp)
0x01e8c31f <+0047> mov -0x30(%ebp),%ecx
0x01e8c322 <+0050> mov %ecx,(%esp)
0x01e8c325 <+0053> call 0x1f0a11e <dyld_stub_object_getClass>
0x01e8c32a <+0058> mov %eax,(%esp)
0x01e8c32d <+0061> call 0x1f09e5a <dyld_stub_class_getName>
0x01e8c332 <+0066> mov %eax,-0x28(%ebp)
0x01e8c335 <+0069> movl $0xa,-0x34(%ebp)
0x01e8c33c <+0076> cld
0x01e8c33d <+0077> lea 0x73a30(%ebx),%edi
0x01e8c343 <+0083> mov %eax,%esi
0x01e8c345 <+0085> mov $0xa,%ecx
0x01e8c34a <+0090> repz cmpsb %es:(%edi),%ds:(%esi)
0x01e8c34c <+0092> mov $0x0,%eax
0x01e8c351 <+0097> je 0x1e8c35d <___forwarding___+109>
0x01e8c353 <+0099> movzbl -0x1(%esi),%eax
0x01e8c357 <+0103> movzbl -0x1(%edi),%ecx
0x01e8c35b <+0107> sub %ecx,%eax
0x01e8c35d <+0109> test %eax,%eax
0x01e8c35f <+0111> jne 0x1e8c3a7 <___forwarding___+183>
0x01e8c361 <+0113> mov 0x95d46(%ebx),%eax
0x01e8c367 <+0119> cmpb $0x0,(%eax)
0x01e8c36a <+0122> jne 0x1e8c680 <___forwarding___+912>
0x01e8c370 <+0128> mov -0x2c(%ebp),%edx
0x01e8c373 <+0131> mov %edx,(%esp)
0x01e8c376 <+0134> call 0x1f0a214 <dyld_stub_sel_getName>
0x01e8c37b <+0139> mov -0x30(%ebp),%ecx
0x01e8c37e <+0142> mov %ecx,0x10(%esp)
0x01e8c382 <+0146> mov %eax,0xc(%esp)
0x01e8c386 <+0150> mov -0x28(%ebp),%eax
0x01e8c389 <+0153> add $0xa,%eax
0x01e8c38c <+0156> mov %eax,0x8(%esp)
0x01e8c390 <+0160> lea 0x9d822(%ebx),%eax
0x01e8c396 <+0166> mov %eax,0x4(%esp)
0x01e8c39a <+0170> movl $0x3,(%esp)
0x01e8c3a1 <+0177> call 0x1eb3040 <CFLog>
0x01e8c3a6 <+0182> int3
BREAK >> 0x01e8c3a7 <+0183> movl $0x11,-0x38(%ebp)
0x01e8c3ae <+0190> cld
0x01e8c3af <+0191> lea 0x79590(%ebx),%edi
0x01e8c3b5 <+0197> mov -0x28(%ebp),%esi
0x01e8c3b8 <+0200> mov $0x11,%ecx
0x01e8c3bd <+0205> repz cmpsb %es:(%edi),%ds:(%esi)
0x01e8c3bf <+0207> mov $0x0,%eax
0x01e8c3c4 <+0212> je 0x1e8c3d0 <___forwarding___+224>
0x01e8c3c6 <+0214> movzbl -0x1(%esi),%eax
0x01e8c3ca <+0218> movzbl -0x1(%edi),%ecx
0x01e8c3ce <+0222> sub %ecx,%eax
0x01e8c3d0 <+0224> mov -0x30(%ebp),%edx
0x01e8c3d3 <+0227> mov %edx,-0x24(%ebp)
0x01e8c3d6 <+0230> test %eax,%eax
0x01e8c3d8 <+0232> jne 0x1e8c3e0 <___forwarding___+240>
0x01e8c3da <+0234> mov 0x4(%edx),%ecx
0x01e8c3dd <+0237> mov %ecx,-0x24(%ebp)
0x01e8c3e0 <+0240> mov 0xa1dbe(%ebx),%esi
0x01e8c3e6 <+0246> mov -0x24(%ebp),%eax
0x01e8c3e9 <+0249> mov %eax,(%esp)
0x01e8c3ec <+0252> call 0x1f0a11e <dyld_stub_object_getClass>
0x01e8c3f1 <+0257> mov %esi,0x4(%esp)
0x01e8c3f5 <+0261> mov %eax,(%esp)
0x01e8c3f8 <+0264> call 0x1f09e72 <dyld_stub_class_respondsToSelector>
0x01e8c3fd <+0269> test %al,%al
0x01e8c3ff <+0271> je 0x1e8c580 <___forwarding___+656>
0x01e8c405 <+0277> mov -0x2c(%ebp),%edx
0x01e8c408 <+0280> mov %edx,0x8(%esp)
0x01e8c40c <+0284> mov %esi,0x4(%esp)
0x01e8c410 <+0288> mov -0x24(%ebp),%ecx
0x01e8c413 <+0291> mov %ecx,(%esp)
0x01e8c416 <+0294> call 0x1f0a0ee <dyld_stub_objc_msgSend>
0x01e8c41b <+0299> mov %eax,-0x20(%ebp)
0x01e8c41e <+0302> mov %eax,-0x1c(%ebp)
0x01e8c421 <+0305> test %eax,%eax
0x01e8c423 <+0307> je 0x1e8c5ac <___forwarding___+700>
0x01e8c429 <+0313> mov 0xa1df6(%ebx),%eax
0x01e8c42f <+0319> mov %eax,0x4(%esp)
0x01e8c433 <+0323> mov -0x1c(%ebp),%edx
0x01e8c436 <+0326> mov %edx,(%esp)
0x01e8c439 <+0329> call 0x1f0a0ee <dyld_stub_objc_msgSend>
0x01e8c43e <+0334> mov (%eax),%edx
0x01e8c440 <+0336> mov 0x18(%edx),%eax
0x01e8c443 <+0339> shr $0x16,%eax
0x01e8c446 <+0342> and $0x1,%eax
0x01e8c449 <+0345> cmp 0xc(%ebp),%eax
0x01e8c44c <+0348> je 0x1e8c498 <___forwarding___+424>
0x01e8c44e <+0350> lea 0x6eaee(%ebx),%eax
0x01e8c454 <+0356> lea 0x7979f(%ebx),%esi
0x01e8c45a <+0362> mov 0xc(%ebp),%ecx
0x01e8c45d <+0365> test %ecx,%ecx
0x01e8c45f <+0367> mov %eax,%edi
0x01e8c461 <+0369> cmove %esi,%edi
0x01e8c464 <+0372> testb $0x40,0x1a(%edx)
0x01e8c468 <+0376> cmovne %eax,%esi
0x01e8c46b <+0379> mov -0x2c(%ebp),%ecx
0x01e8c46e <+0382> mov %ecx,(%esp)
0x01e8c471 <+0385> call 0x1f0a214 <dyld_stub_sel_getName>
0x01e8c476 <+0390> mov %edi,0x10(%esp)
0x01e8c47a <+0394> mov %esi,0xc(%esp)
0x01e8c47e <+0398> mov %eax,0x8(%esp)
0x01e8c482 <+0402> lea 0x9d852(%ebx),%eax
0x01e8c488 <+0408> mov %eax,0x4(%esp)
0x01e8c48c <+0412> movl $0x4,(%esp)
0x01e8c493 <+0419> call 0x1eb3040 <CFLog>
0x01e8c498 <+0424> mov -0x20(%ebp),%eax
0x01e8c49b <+0427> mov %eax,0x8(%esp)
0x01e8c49f <+0431> mov 0xa1dba(%ebx),%eax
0x01e8c4a5 <+0437> mov %eax,0x4(%esp)
0x01e8c4a9 <+0441> mov 0xa1e76(%ebx),%eax
0x01e8c4af <+0447> mov %eax,(%esp)
0x01e8c4b2 <+0450> call 0x1f0a0ee <dyld_stub_objc_msgSend>
0x01e8c4b7 <+0455> mov %eax,%edi
0x01e8c4b9 <+0457> mov 0xa1dde(%ebx),%eax
Here's what's more likely:
Something does instanceVariable = [NSArray arrayWithObjects:..., nil];
The NSArray was not retained, so it gets released at the end of the run loop.
Something taps the row. The NSArray's memory gets reused to make your ClassRoster object.
You navigate out of ClassRoster, and it gets released and dealloced.
Something tries to access instanceVariable. It points to the memory that used to be a NSArray, but has now been overwritten by ClassRoster.
Try setting the environment variable NSZombieEnabled=YES (in Project -> Edit Active Executable). You can also set NSDeallocateZombies=NO, but AIUI that's the default.
Turn it off once you're finished debugging.
EDIT: Oops (I should've realized you had zombies on, and looked at the method name).
If you run it in the debugger (you might need breakpoints active), it should stop at the thing that called controllerWillChangeContent:. Perhaps your ClassRoster is being set as the delegate for something, and is getting a delegate callback after it's been dealloced? I always set the relevant delegates to nil in dealloc to prevent problems like this.
I don't think you have over-released the instance.
To me, it looks like the deallocated instance is of some other class but receives a message from ClassRoaster.
Can you post the error message and the stack trace from the moment you app crashes?
'Illegal attempt to establish a relationship 'myClass' between objects in different contexts'
That line describes the issue. You are probably using code from an Apple example that has you building more than one NSManagedObjectContext correct? Perhaps the code suggested to create a second one so that you can easily cancel out of an edit or some such?
That is your problem. You are trying to connect two objects that are in two different NSManagedObjectContext instances. Consider each NSManagedObjectContext to be a sandbox and you can't mix them.
However, you do not need to have more than one NSManagedObjectContext. The example that does that is a very bad example. A single NSManagedObjectContext is more than sufficient for any single threaded application. Remove the second NSManagedObjectContext from your application and this issue will go away.
Update
I found the error. You cannot create a NSManagedObject with -init. That is not the designated initializer for an NSManagedObject. You must either create it with
-initWithEntity: insertIntoManagedObjectContext:
or use the class method
+[NSEntityDescription insertNewObjectForEntityForName: inManagedObjectContext]
Those are the only two valid ways to create a new NSManagedObject.]
Update
I strongly suggest you use better naming conventions, ClassRosterViewController is far more descriptive. ClassRoster really sounds like data object.
My original assumption still stands, somewhere, somehow you are trying to connect two NSManagedObject instances that do not belong to the same NSManagedObjectContext. Either you have two instances of NSManagedObjectContext or you are creating a NSManagedObject without an associated NSManagedObjectContext.
However, my responses are based around the error message that is in your question. Where are you seeing the error that is in your title. Can you paste that stack trace as well?
just had the same problem
the problem was because i had released the delegate instead of setting it to nil
good luck!