我正在检查一些崩溃,它们都有信号 SIGSEGV,原因是 SEGV_ACCERR。在搜索 SEGV_ACCERR 之后,我发现最接近人类可读解释的是:Invalid Permissions for object
这在更一般意义上意味着什么?什么时候会出现 SEGV_ACCERR?有没有关于这个原因的更具体的文件?
我正在检查一些崩溃,它们都有信号 SIGSEGV,原因是 SEGV_ACCERR。在搜索 SEGV_ACCERR 之后,我发现最接近人类可读解释的是:Invalid Permissions for object
这在更一般意义上意味着什么?什么时候会出现 SEGV_ACCERR?有没有关于这个原因的更具体的文件?
这是我最常在 64 位 iOS 设备上看到的错误,如果多个线程读取并更改 ARC 下的变量,就会发生这种错误。例如,我今天修复了一个崩溃,其中多个后台线程正在读取和使用静态 NSDate 和 NSString 变量并更新它们而不进行任何类型的锁定或排队。
正如我在崩溃日志中多次看到的那样,在多个线程上使用核心数据对象也会导致此崩溃。
我也使用 Crittercism,这个特殊的崩溃是一个只影响 64 位设备的 SEGV_ACCERR。
正如sigaction的手册页中所述,SEGV_ACCERR是 SIGSEGV 的信号代码,它指定映射对象的无效权限。与 SEGV_MAPERR 表示地址未映射到有效对象相反,SEGV_ACCERR 表示地址匹配对象,但可以肯定的是,它既不是好的对象,也不是允许进程访问的对象。
在代码尝试从“文本”以外的地方执行的情况下,我已经看到了这一点。
例如,如果您的指针指向堆或堆栈中的函数并且您尝试执行该代码(从堆或堆栈),CPU 会抛出此异常。
SEGV_ACCERR
由于堆栈溢出,可能会得到 a 。具体来说,这在我的 Android ARM64 上发生了以下情况:
VeryLargeStruct s;
s = {}; // SEGV_ACCERR
似乎零初始化创建了一个导致堆栈溢出的临时性。这只发生在-O0
; 大概是在更高的优化级别上对临时进行了优化。
在 android arm64 上,如果 stack.cpp 包含:
struct VeryLargeStruct {
int array[4096*4096];
};
int main() {
struct VeryLargeStruct s;
s = {};
}
并输入:
aarch64-linux-android26-clang++ -std=c++20 -g -DANDROID_STL=c++_static -static-libstdc++ stack.cpp -o stack
adb push stack /data/local/tmp
adb shell /data/local/tmp/stack
/data/tombstones/tombstone_01 包含一个 SEGV_MAPERR,而不是 SEGV_ACCERR:
id: 11363, tid: 11363, name: stack >>> /data/local/tmp/stack <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x7ff2d02dd8
我得到 SEGV_ACCERR,当 const.c 包含:
int main() {
char *str="hello";
str[0]='H';
}
然后 /data/tombstones/tombstone_00 包含:
pid: 9844, tid: 9844, name: consts >>> /data/local/tmp/consts <<<
Signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x55d10674e8