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

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!

Related

Is "step-out" / "step-over-instruction" broken in Simics 2021.24?

Step-out seems to be broken in Simics 2021.24. I did "enable-debugger" but it still doesn't work. Please see below:
simics>
[board.mb.cpu0.core[0][0]] cs:0x00000000def963ae p:0x0def963ae sbb rax,rax
sbb rax,rax
cs:0x00000000def963ae p:0x0def963ae sbb rax,rax
cs:0x00000000def963b1 p:0x0def963b1 and rax,rcx
cs:0x00000000def963b4 p:0x0def963b4 mov rdi,qword ptr [rsp+0x8]
cs:0x00000000def963b9 p:0x0def963b9 ret
cs:0x00000000def963ba p:0x0def963ba mov rcx,r11
cs:0x00000000def963bd p:0x0def963bd lea rax,[r9-0x1]
cs:0x00000000def963c1 p:0x0def963c1 shr rdx,cl
cs:0x00000000def963c4 p:0x0def963c4 cmp rdx,rax
cs:0x00000000def963c7 p:0x0def963c7 jb 0xdef96363
cs:0x00000000def963c9 p:0x0def963c9 sub rdx,r9
simics> step-out
simics> da %rip 10
cs:0x00000000def963ae p:0x0def963ae sbb rax,rax
cs:0x00000000def963b1 p:0x0def963b1 and rax,rcx
cs:0x00000000def963b4 p:0x0def963b4 mov rdi,qword ptr [rsp+0x8]
cs:0x00000000def963b9 p:0x0def963b9 ret
cs:0x00000000def963ba p:0x0def963ba mov rcx,r11
cs:0x00000000def963bd p:0x0def963bd lea rax,[r9-0x1]
cs:0x00000000def963c1 p:0x0def963c1 shr rdx,cl
cs:0x00000000def963c4 p:0x0def963c4 cmp rdx,rax
cs:0x00000000def963c7 p:0x0def963c7 jb 0xdef96363
cs:0x00000000def963c9 p:0x0def963c9 sub rdx,r9
Likewise "step-over-instruction" doesn't seem to step over calls, it steps into them...
simics> step-over-instruction
call rax
cs:0x00000000dee41d19 p:0x0dee41d19 call rax
cs:0x00000000dee41d1b p:0x0dee41d1b jmp 0xdee41d2d
cs:0x00000000dee41d1d p:0x0dee41d1d mov rax,qword ptr [rip+0x265bc]
cs:0x00000000dee41d24 p:0x0dee41d24 mov rcx,rbp
cs:0x00000000dee41d27 p:0x0dee41d27 call qword ptr [rax+0xf8]
cs:0x00000000dee41d2d p:0x0dee41d2d cmp si,r13w
cs:0x00000000dee41d31 p:0x0dee41d31 jb 0xdee41ced
cs:0x00000000dee41d33 p:0x0dee41d33 mov r13d,0x400
cs:0x00000000dee41d39 p:0x0dee41d39 mov eax,dword ptr [rbx+0x114]
cs:0x00000000dee41d3f p:0x0dee41d3f sub eax,0x10
simics> step-over-instruction
sub rsp,0x28
cs:0x00000000dee39160 p:0x0dee39160 sub rsp,0x28
cs:0x00000000dee39164 p:0x0dee39164 test rdx,rdx
cs:0x00000000dee39167 p:0x0dee39167 je 0xdee39179
cs:0x00000000dee39169 p:0x0dee39169 mov rax,qword ptr [rip+0x1b58]
cs:0x00000000dee39170 p:0x0dee39170 mov rcx,rdx
cs:0x00000000dee39173 p:0x0dee39173 call qword ptr [rax+0xf8]
cs:0x00000000dee39179 p:0x0dee39179 add rsp,0x28
cs:0x00000000dee3917d p:0x0dee3917d ret
cs:0x00000000dee3917e p:0x0dee3917e int3
cs:0x00000000dee3917f p:0x0dee3917f int3
simics> print -x %rax
0xdee39160
So you can see it called to where rax was set, instead of stepping over the call.
both the step-out and step-over-instruction requires debug information. You can add debug information with add-symbol-file.
If you don't have the debug information, you will have to set a breakpoint or run until the instruction after the call. In this case, that would be one of:
bp.memory.run-until -x address = p:0x0dee41d1b
or
bp.memory.break -x address = p:0x0dee41d1b
c
#IAmIntel

Why is using isEmpty preferable over a comparison with an empty string literal is Swift?

The String type is Swift has a property named isEmpty that indicates whether a string has no characters.
I'd like to know if there's any difference between using isEmpty and checking the equality to an empty string literal. In other words, is myString.isEmpty any better than myString == ""?
I did some research and came across the following recommendations:
String struct reference at Apple developer documentation (as well as the Swift Language Guide) recommends using isEmpty instead of checking the string's length:
To check whether a string is empty, use its isEmpty property instead of comparing the length of one of the views to 0. Unlike with isEmpty, calculating a view’s count property requires iterating through the elements of the string.
Answer to a slightly different question from 2015 on StackOverflow by Rob Napier states the following:
The empty string is the only empty string, so there should be no cases where string.isEmpty() does not return the same value as string == "". They may do so in different amounts of time and memory, of course. Whether they use different amounts of time and memory is an implementation detail not described, but isEmpty is the preferred way to check in Swift (as documented).
Some blog posts also recommend using isEmpty especially instead of checking if the string's length is 0.
None of these sources however say anything against comparing with an empty literal.
It seems totally reasonable to avoid constructions like myString.count == 0 because of obvious performance and readability drawbacks. I also get the fact that myString.isEmpty is more readable than myString == "".
Still, I'm curious whether the comparison with an empty string literal is bad. Does it really have any memory or performance implications? Perhaps the Swift compiler is so smart these days that it will produce the same binary code for myString.isEmpty and myString == ""? My gut feeling is that the difference should be negligible or even non-existent but I don't have proofs.
I realize it's not really a practical question though, however I'll be grateful if someone could share some insights how these two alternatives work on a lower level and whether there are any differences. Thank you all in advance.
As a note, isEmpty is the preferred/recommended method to check the emptiness of a collection, as all Collection types guarantee that isEmpty returns in O(1) (or at least this holds for the standard library collections). The equality operator make no such guarantees, thus if you're only interested about the collection having or not having elements (e.g. to launch a processing operation), then isEmpty is definitively the way to go.
Now, to see what's happening under the hood when using isEmpty vs when comparing to an empty string, we can use the generated assembly.
func testEmpty(_ str: String) -> Bool { str.isEmpty }
results in the following assembly code:
_$s3CL29testEmptyySbSSF:
0000000100002c70 push rbp
0000000100002c71 mov rbp, rsp
0000000100002c74 mov rax, rsi
0000000100002c77 shr rax, 0x38
0000000100002c7b and eax, 0xf
0000000100002c7e movabs rcx, 0xffffffffffff
0000000100002c88 and rcx, rdi
0000000100002c8b bt rsi, 0x3d
0000000100002c90 cmovae rax, rcx
0000000100002c94 test rax, rax
0000000100002c97 sete al
0000000100002c9a pop rbp
0000000100002c9b ret
while
func testEqual(_ str: String) -> Bool { str == "" }
generates this:
_$s3CL29testEqualySbSSF:
0000000100002cd0 push rbp
0000000100002cd1 mov rbp, rsp
0000000100002cd4 movabs rcx, 0xe000000000000000
0000000100002cde test rdi, rdi
0000000100002ce1 jne 0x100002cec
0000000100002ce3 cmp rsi, rcx
0000000100002ce6 jne 0x100002cec
0000000100002ce8 mov al, 0x1
0000000100002cea pop rbp
0000000100002ceb ret
0000000100002cec xor edx, edx ; XREF=_$s3CL29testEqualySbSSF+17, _$s3CL29testEqualySbSSF+22
0000000100002cee xor r8d, r8d
0000000100002cf1 pop rbp
0000000100002cf2 jmp imp___stubs__$ss27_stringCompareWithSmolCheck__9expectingSbs11_StringGutsV_ADs01_G16ComparisonResultOtF
; endp
Both assemblies are generated in the Release mode, with all optimizations enabled. Seems that for the isEmpty call the compiler is able to take some shortcuts since it knows about the internal String structure.
But we can take that away by making our functions generic:
func testEmpty<S: StringProtocol>(_ str: S) -> Bool { str.isEmpty }
produces
_$s3CL29testEmptyySbxSyRzlF:
0000000100002bd0 push rbp
0000000100002bd1 mov rbp, rsp
0000000100002bd4 push r13
0000000100002bd6 push rax
0000000100002bd7 mov rax, rsi
0000000100002bda mov rcx, qword [ds:rdx+8]
0000000100002bde mov rsi, qword [ds:rcx+8]
0000000100002be2 mov r13, rdi
0000000100002be5 mov rdi, rax
0000000100002be8 call imp___stubs__$sSl7isEmptySbvgTj
0000000100002bed add rsp, 0x8
0000000100002bf1 pop r13
0000000100002bf3 pop rbp
0000000100002bf4 ret
; endp
, while
func testEqual<S: StringProtocol>(_ str: S) -> Bool { str == "" }
produces
_$s3CL29testEqualySbxSyRzlF:
0000000100002c00 push rbp
0000000100002c01 mov rbp, rsp
0000000100002c04 push r14
0000000100002c06 push r13
0000000100002c08 push rbx
0000000100002c09 sub rsp, 0x18
0000000100002c0d mov r14, rdx
0000000100002c10 mov r13, rsi
0000000100002c13 mov rbx, rdi
0000000100002c16 mov qword [ss:rbp+var_28], 0x0
0000000100002c1e movabs rax, 0xe000000000000000
0000000100002c28 mov qword [ss:rbp+var_20], rax
0000000100002c2c call _$sS2SSysWl
0000000100002c31 mov rcx, qword [ds:imp___got__$sSSN]
0000000100002c38 lea rsi, qword [ss:rbp+var_28]
0000000100002c3c mov rdi, rbx
0000000100002c3f mov rdx, r13
0000000100002c42 mov r8, r14
0000000100002c45 mov r9, rax
0000000100002c48 call imp___stubs__$sSysE2eeoiySbx_qd__tSyRd__lFZ
0000000100002c4d add rsp, 0x18
0000000100002c51 pop rbx
0000000100002c52 pop r13
0000000100002c54 pop r14
0000000100002c56 pop rbp
0000000100002c57 ret
; endp
Similar results, the isEmpty code results is less assembly code, which makes it faster.

Windbg disassembler address resolution

I was analysing a complete memory dump and I applied Windbg uf command to see what a function does
0: kd> uf profsvc!CUserProfileService::_RegisterGPNotification
This is the part of the output. I wonder why the address in parentheses is different than the address of profsvc!CUserProfileService::_RegisterGPNotification+0x44 which should be
000007fe fb149276
but is
000007fe fb155019.
When I try to unassembled the address 000007fe fb155019 with u it points to
profsvc!CUserProfileService::_RegisterGPNotification+0x44:
I’m really puzzled, any help deeply appreciated.
OUTPUT from WinDBG
….
profsvc!CUserProfileService::_RegisterGPNotification+0x2e:
000007fe`fb14925e ba01000000 mov edx,1
000007fe`fb149263 488bc8 mov rcx,rax
000007fe`fb149266 ff157c410200 call qword ptr [profsvc!_imp_RegisterGPNotification (000007fe`fb16d3e8)]
000007fe`fb14926c 85c0 test eax,eax
000007fe`fb14926e 0f84a5bd0000 je profsvc!CUserProfileService::_RegisterGPNotification+0x44 (**000007fe`fb155019**)
profsvc!CUserProfileService::_RegisterGPNotification+0x40:
000007fe`fb149274 33db xor ebx,ebx
000007fe`fb149276 eb00 jmp profsvc!CUserProfileService::_RegisterGPNotification+0x66 (000007fe`fb149278) Branch
profsvc!CUserProfileService::_RegisterGPNotification+0x66:
000007fe`fb149278 488b0d31b00200 mov rcx,qword ptr [profsvc!WPP_GLOBAL_Control (000007fe`fb1742b0)]
000007fe`fb14927f 488d052ab00200 lea rax,[profsvc!WPP_GLOBAL_Control (000007fe`fb1742b0)]
000007fe`fb149286 483bc8 cmp rcx,rax
000007fe`fb149289 740a je profsvc!CUserProfileService::_RegisterGPNotification+0x94 (000007fe`fb149295) Branch
0: kd> u 000007fe`fb155019
profsvc!CUserProfileService::_RegisterGPNotification+0x44:
000007fe`fb155019 ?? ???
^ Memory access error in 'u 000007fe`fb155019'
This is due to optimization, see the following MSDN article:
https://msdn.microsoft.com/en-us/library/windows/hardware/ff541382(v=vs.85).aspx

Read a sector to address zero

%include "init.inc"
[org 0x0]
[bits 16]
jmp 0x07C0:start_boot
start_boot:
mov ax, cs
mov ds, ax
mov es, ax
load_setup:
mov ax, SETUP_SEG
mov es, ax
xor bx, bx
mov ah, 2 ; copy data to es:bx from disk.
mov al, 1 ; read a sector.
mov ch, 0 ; cylinder 0
mov cl, 2 ; read data since sector 2.
mov dh, 0 ; Head = 0
mov dl, 0 ; Drive = 0
int 0x13 ; BIOS call.
jc load_setup
lea si, [msg_load_setup]
call print
jmp $
print:
print_beg:
mov ax, 0xB800
mov es, ax
xor di, di
print_msg:
mov al, byte [si]
mov byte [es:di], al
or al, al
jz print_end
inc di
mov byte [es:di], BG_TEXT_COLOR
inc di
inc si
jmp print_msg
print_end:
ret
msg_load_setup db "Loading setup.bin was completed." , 0
times 510-($-$$) db 0
dw 0xAA55
I want to load setup.bin to memory address zero. So, I input 0 value to es register (SETUP_SEG = 0). bx, too. But it didn't work. then, I have a question about this issue. My test is below.
SETUP_SEG's value
0x0000 : fail
0x0010 : success
0x0020 : fail
0x0030 : fail
0x0040 : fail
0x0050 : success
I can't understand why this situation was happened. All test was carried out on VMware. Does anyone have an idea ?
I'm not sure if this is your problem, but your trying to load setup.bin in the Real Mode IVT (Interrupt Vector Table). The IVT contains the location of each interrupt, so I'm assuming that your boatloader is overwriting them when it loads setup.bin into memory! Interrupts can be sneaky and tricky, since they can be called even if you didn't call them. Any interrupt vector you overwrote will likely cause undefined behavior when called, which will cause some problems.
I suggest setting SETUP_SEG to a higher number like 0x2000 or 0x3000, but the lowest you could safely go is 0x07E0. The Osdev Wiki and Wikipedia have some helpful information on conventional memory and memory mapping.
I hope this helps!

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.