" EXC_BAD_ACCESS" vs“分段错误”。实际上是否相同? [英] "EXC_BAD_ACCESS" vs "Segmentation fault". Are both same practically?

查看:181
本文介绍了" EXC_BAD_ACCESS" vs“分段错误”。实际上是否相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的前几个虚拟应用程序中(在学习的同时练习)我遇到了很多 EXC_BAD_ACCESS ,它以某种方式告诉我Bad-Access是:你正在接触/访问您不应该访问的对象,因为它尚未分配或已取消分配,或者您无权访问它。

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.

请看这个具有错误访问问题的示例代码,因为我正在尝试修改 const

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.

我想知道两件事。
一个
,我是否正确 objective-C的EXC_BAD_ACCESS ?我能做对吗?

I wanna know two things. One, Am I right about objective-C's EXC_BAD_ACCESS ? Do I get it right ?

第二次,是 EXC_BAD_ACCESS和分段错误同样的事情和Apple刚刚即兴创作了它的名字?

Second, Are EXC_BAD_ACCESS and Segmentation fault same things and Apple has just improvised its name?

推荐答案

不, EXC_BAD_ACCESS SIGSEGV 不同。

EXC_BAD_ACCESS 是Mach异常(Mach和xnu的组合构成Mac OS X内核),而 SIGSEGV 是POSIX信号。当崩溃发生时,原因为 EXC_BAD_ACCESS ,通常在以下情况后立即在括号中报告信号:例如, EXC_BAD_ACCESS(SIGSEGV)。但是,有一个其他可以与 EXC_BAD_ACCESS 一起看到的POSIX信号:它是 SIGBUS ,报告为 EXC_BAD_ACCESS (SIGBUS)

EXC_BAD_ACCESS is a Mach exception (A combination of Mach and xnu compose the Mac OS X kernel), while SIGSEGV is a POSIX signal. When crashes occur with cause given as EXC_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 with EXC_BAD_ACCESS: It is SIGBUS, reported as EXC_BAD_ACCESS(SIGBUS).

SIGSEGV 在阅读/写作时最常出现一个完全没有映射到内存映射中的地址,比如 NULL 指针,或尝试写入只读内存位置(如上例所示)。另一方面,即使对于进程具有合法访问权限的地址,也可以看到 SIGBUS 。例如, SIGBUS 可以使用假定对齐地址的指令或尝试写入的进程来打击一个敢于从未对齐的内存地址加载/存储的进程。一个没有特权级别的页面。

SIGSEGV is most often seen when reading from/writing to an address that is not at all mapped in the memory map, like the NULL 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.

因此 EXC_BAD_ACCESS 最好被理解为 SIGSEGV SIGBUS 的集合,并且指的是错误访问内存的所有方法(是因为所说的内存不存在,或者确实存在但是未对齐,特权或诸如此类,因此它的名称: exception - bad access

Thus EXC_BAD_ACCESS can best be understood as the set of both SIGSEGV and SIGBUS, 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.

为了大饱眼福,这里是代码,在 xnu-1504.15.3(Mac OS X 10.6.8 build 10K459)内核源代码中,文件 bsd / uxkern / ux_exception.c 从行 429 开始,转换 EXC_BAD_ACCESS SIGSEGV SIGBUS

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, file bsd/uxkern/ux_exception.c beginning at line 429, that translates EXC_BAD_ACCESS to either SIGSEGV or 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;
    ...



根据您的其他问题编辑



请注意,此处的异常并未引用语言级别的异常,类型可能会遇到类似的语法糖类try {} catch {} blocks。这里的异常是指CPU在遇到程序中某些类型的错误时的行为(它们可能是也可能不是致命的),如空指针取消引用,需要外部干预。

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.

当发生这种情况时,会说CPU 引发通常称为异常中断的内容。这意味着CPU保存它正在做的事情(上下文)并处理异常情况。

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.

处理这种特殊情况,CPU 开始执行任何异常处理代码( catch -blocks等)应用。它首先通过开始执行内核提供的一段代码中断服务程序来提供OS控制。这是一段代码,用于确定哪个流程发生了什么,以及该怎么做。操作系统因此有机会判断情况并采取它想要的操作。

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.

它为无效的内存访问所做的操作(例如空指针取消引用)是用 EXC_BAD_ACCESS(SIGSEGV)表示有罪过程。它对未对齐的内存访问所采取的操作是用 EXC_BAD_ACCESS(SIGBUS)向有罪进程发出信号。还有许多其他特殊情况和相应的操作,并非所有情况都涉及信号。

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 with EXC_BAD_ACCESS(SIGBUS). There are many other exceptional situations and corresponding actions, not all of which involve signals.

我们现在回到您的程序环境中。如果您的程序收到 SIGSEGV SIGBUS 信号,它将调用信号处理程序已为该信号安装,或者如果没有则安装默认值。人们很少为 SIGSEGV SIGBUS 安装自定义处理程序,默认处理程序会关闭程序,所以你通常得到的是你的程序被关闭。

We're now back in the context of your program. If your program receives the SIGSEGV or SIGBUS 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 for SIGSEGV and SIGBUS and the default handlers shut down your program, so what you usually get is your program being shut down.

因此,这种异常完全不同于排序 throw 中尝试{} -blocks和 catch {} es。 这些异常仅在应用程序中处理,而不涉及操作系统 。这里发生的事情是 throw 语句只是一个美化的跳转到最内层的 catch 块来处理该异常。当异常通过堆栈冒泡时,它展开它背后的堆栈,运行析构函数等等。

This sort of exceptions is therefore completely unlike the sort one throws in try{}-blocks and catch{}es. Those exceptions are handled purely within the application, without involving the OS at all. Here what happens is that a throw statement is simply a glorified jump to the inner-most catch block that handles that exception. As the exception bubbles through the stack, it unwinds the stack behind it, running destructors and suchlike as needed.

这篇关于" EXC_BAD_ACCESS" vs“分段错误”。实际上是否相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆