In my first few dummy apps(for practice while learning) I have come across a lot of EXC_BAD_ACCESS
, that somehow taught me Bad-Access is : You are touching/Accessing a object that you shouldn't because either it is not allocated yet or deallocated or simply you are not authorized to access it.
Look at this sample code that has bad-access issue because I am trying to modify a const
:
-(void)myStartMethod{
NSString *str = @"testing";
const char *charStr = [str UTF8String];
charStr[4] = '\0'; // bad access on this line.
NSLog(@"%s",charStr);
}
While Segmentation fault says : Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory (more description here.
I wanna know two things.
One, Am I right about objective-C's EXC_BAD_ACCESS
? Do I get it right ?
Second, Are EXC_BAD_ACCESS and Segmentation fault
same things and Apple has just improvised its name?
No,
EXC_BAD_ACCESS
is not the same asSIGSEGV
.EXC_BAD_ACCESS
is a Mach exception (A combination of Mach and xnu compose the Mac OS X kernel), whileSIGSEGV
is a POSIX signal. When crashes occur with cause given asEXC_BAD_ACCESS
, often the signal is reported in parentheses immediately after: For instance,EXC_BAD_ACCESS(SIGSEGV)
. However, there is one other POSIX signal that can be seen in conjunction withEXC_BAD_ACCESS
: It isSIGBUS
, reported asEXC_BAD_ACCESS(SIGBUS)
.SIGSEGV
is most often seen when reading from/writing to an address that is not at all mapped in the memory map, like theNULL
pointer, or attempting to write to a read-only memory location (as in your example above).SIGBUS
on the other hand can be seen even for addresses the process has legitimate access to. For instance,SIGBUS
can smite a process that dares to load/store from/to an unaligned memory address with instructions that assume an aligned address, or a process that attempts to write to a page for which it has not the privilege level to do so.Thus
EXC_BAD_ACCESS
can best be understood as the set of bothSIGSEGV
andSIGBUS
, and refers to all ways of incorrectly accessing memory (whether because said memory does not exist, or does exist but is misaligned, privileged or whatnot), hence its name: exception – bad access.To feast your eyes, here is the code, within the
xnu-1504.15.3 (Mac OS X 10.6.8 build 10K459)
kernel source code, filebsd/uxkern/ux_exception.c
beginning at line429
, that translatesEXC_BAD_ACCESS
to eitherSIGSEGV
orSIGBUS
.Edit in relation to another of your questions
Please note that exception here does not refer to an exception at the level of the language, of the type one may catch with syntactical sugar like
try{} catch{}
blocks. Exception here refers to the actions of a CPU on encountering certain types of mistakes in your program (they may or may not be be fatal), like a null-pointer dereference, that require outside intervention.When this happens, the CPU is said to raise what is commonly called either an exception or an interrupt. This means that the CPU saves what it was doing (the context) and deals with the exceptional situation.
To deal with such an exceptional situation, the CPU does not start executing any "exception-handling" code (
catch
-blocks or suchlike) in your application. It first gives the OS control, by starting to execute a kernel-provided piece of code called an interrupt service routine. This is a piece of code that figures out what happened to which process, and what to do about it. The OS thus has an opportunity to judge the situation, and take the action it wants.The action it does for an invalid memory access (such as a null pointer dereference) is to signal the guilty process with
EXC_BAD_ACCESS(SIGSEGV)
. The action it does for a misaligned memory access is to signal the guilty process withEXC_BAD_ACCESS(SIGBUS)
. There are many other exceptional situations and corresponding actions, not all of which involve signals.We're now back in the context of your program. If your program receives the
SIGSEGV
orSIGBUS
signals, it will invoke the signal handler that was installed for that signal, or the default one if none was. It is rare for people to install custom handlers forSIGSEGV
andSIGBUS
and the default handlers shut down your program, so what you usually get is your program being shut down.This sort of exceptions is therefore completely unlike the sort one
throw
s intry{}
-blocks andcatch{}
es. Those exceptions are handled purely within the application, without involving the OS at all. Here what happens is that athrow
statement is simply a glorified jump to the inner-mostcatch
block that handles that exception. As the exception bubbles through the stack, it unwinds the stack behind it, running destructors and suchlike as needed.Basically yes, indeed an EXC_BAD_ACCESS is usually paired with a SIGSEGV which is a signal that warns about the segmentation failure.
A segmentation failure is risen whenever you are working with a pointer that points to invalid data (maybe not belonging to the process, maybe read-only, maybe an invalid address in general).
Don't think about the segmentation fault in terms of "accessing an object", you are accessing a memory location, so an address. That address must be considered coherent by the OS memory protection system.
Not all errors which are related to accessing invalid data can be tracked by the memory manager, think about a pointer to a stack allocated variable, which is considered valid although its content is not valid anymore upon restoring the stack frame.