11 c xcode exc-bad-access objective-c ios
在我的前几个虚拟应用程序中(为了练习而学习)我遇到了很多EXC_BAD_ACCESS,不知何故教会我Bad-Access是:你正在触摸/访问一个你不应该因为它尚未分配或取消分配的对象或者只是您无权访问它.
看看这个具有错误访问问题的示例代码,因为我试图修改一个const:
-(void)myStartMethod{
NSString *str = @"testing";
const char *charStr = [str UTF8String];
charStr[4] = '\0'; // bad access on this line.
NSLog(@"%s",charStr);
}
Run Code Online (Sandbox Code Playgroud)
虽然分段错误说:分段错误是由访问"不属于您"的内存引起的一种特定错误.它是一种帮助机制,可以防止破坏内存并引入难以调试的内存错误.每当你遇到段错误时,你就知道你在做错了记忆(这里有更多描述).
我想知道两件事.一,我是对的objective-C's EXC_BAD_ACCESS吗?我做对了吗?
第二,EXC_BAD_ACCESS and Segmentation fault同样的事情和Apple刚刚即兴创作了它的名字吗?
Iwi*_*ist 22
不,EXC_BAD_ACCESS不一样SIGSEGV.
EXC_BAD_ACCESS是Mach异常(Mach和xnu的组合构成Mac OS X内核),SIGSEGV而是POSIX信号.当崩溃发生且原因给定时EXC_BAD_ACCESS,通常在以下情况后立即在括号中报告信号:例如,EXC_BAD_ACCESS(SIGSEGV).但是,还有另外一个POSIX信号可以与EXC_BAD_ACCESS以下内容一起看:它被SIGBUS报告为EXC_BAD_ACCESS(SIGBUS).
SIGSEGV在读取/写入一个完全没有映射到内存映射中的地址(如NULL指针)或尝试写入只读内存位置时(例如上面的示例中),最常见到这种情况.SIGBUS另一方面,即使对于进程具有合法访问权限的地址也可以看到.例如,SIGBUS可以使用假设已对齐的地址的指令,或者尝试写入其没有特权级别的页面的进程,来打击一个敢于从未对齐的内存地址加载/存储的进程.
因此,EXC_BAD_ACCESS可以最好地理解为集两者的SIGSEGV和SIGBUS,而指的是不正确地访问内存中的所有方面(无论是因为说内存不存在,或不存在,但没有对齐,特权或诸如此类的东西),因此它的名字:异常-错误访问.
为了大饱眼福,这里是代码,在xnu-1504.15.3 (Mac OS X 10.6.8 build 10K459)内核源代码中,bsd/uxkern/ux_exception.c从行开始的文件429,转换EXC_BAD_ACCESS为SIGSEGV或者SIGBUS.
/*
* ux_exception translates a mach exception, code and subcode to
* a signal and u.u_code. Calls machine_exception (machine dependent)
* to attempt translation first.
*/
static
void ux_exception(
int exception,
mach_exception_code_t code,
mach_exception_subcode_t subcode,
int *ux_signal,
mach_exception_code_t *ux_code)
{
/*
* Try machine-dependent translation first.
*/
if (machine_exception(exception, code, subcode, ux_signal, ux_code))
return;
switch(exception) {
case EXC_BAD_ACCESS:
if (code == KERN_INVALID_ADDRESS)
*ux_signal = SIGSEGV;
else
*ux_signal = SIGBUS;
break;
case EXC_BAD_INSTRUCTION:
*ux_signal = SIGILL;
break;
...
Run Code Online (Sandbox Code Playgroud)
请注意,除了在这里的语言水平不是指一个例外,一个类型的可以用相同的语法糖赶try{} catch{}块.这里的异常是指CPU在遇到程序中某些类型的错误时的行为(它们可能是也可能不是致命的),如空指针解除引用,需要外部干预.
当发生这种情况时,CPU会提升通常称为异常或中断的内容.这意味着CPU保存它正在做的事情(上下文)并处理异常情况.
为了应对这样的特殊情况,CPU就没有开始执行任何 "异常处理"代码(catch在应用程序-blocks或类似的东西).它首先通过开始执行内核提供的一段称为中断服务程序的代码来提供OS控制.这是一段代码,用于确定哪个流程发生了什么,以及该怎么做.因此,操作系统有机会判断情况,并采取它想要的行动.
它为无效的内存访问(例如空指针取消引用)所做的操作是用来表示有罪的进程EXC_BAD_ACCESS(SIGSEGV).它为未对齐的内存访问所做的操作是用来表示有罪的进程EXC_BAD_ACCESS(SIGBUS).还有许多其他例外情况和相应的行动,并非所有情况都涉及信号.
我们现在回到您的计划的背景下.如果程序收到SIGSEGV或SIGBUS发出信号,它将调用为该信号安装的信号处理程序,如果没有,则调用默认的信号处理程序.人们很少为其安装自定义处理程序,SIGSEGV并且SIGBUS默认处理程序会关闭程序,因此您通常会关闭程序.
因此,这种异常完全不同于throwin- try{}blocks和catch{}es中的排序.这些异常仅在应用程序内处理,而根本不涉及操作系统.这里发生的事情是,一个throw语句只是catch对处理该异常的最内部块的美化跳转.作为异常气泡通过堆,它退绕堆叠它的后面,根据需要运行析构函数和诸如此类.
基本上是的,实际上EXC_BAD_ACCESS通常与SIGSEGV配对,SIGSEGV是警告分段失败的信号。
每当您使用指向无效数据的指针(可能不属于该进程,可能是只读的,通常可能是无效地址)时,就会出现分段失败。
不要从“访问对象”的角度考虑分段错误,您正在访问内存位置,因此是地址。操作系统内存保护系统必须认为该地址是一致的。
并非所有与访问无效数据相关的错误都可以被内存管理器跟踪,想想一个指向堆栈分配变量的指针,尽管它的内容在恢复堆栈帧时不再有效,但它被认为是有效的。
| 归档时间: |
|
| 查看次数: |
2365 次 |
| 最近记录: |