为什么这个EXC_BAD_ACCESS用很长很长,而不是与诠释发生呢? [英] Why does this EXC_BAD_ACCESS happen with long long and not with int?

查看:177
本文介绍了为什么这个EXC_BAD_ACCESS用很长很长,而不是与诠释发生呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用一张code,与数据序列化的交易碰上 EXC_BAD_ACCESS 。在code不仅不能对设备(iPhone),而不是在模拟器。它也不能只在某些特定的数据类型。

I've run into a EXC_BAD_ACCESS with a piece of code that deals with data serialization. The code only fails on device (iPhone) and not on simulator. It also fails only on certain data types.

下面是测试code能重现问题:

Here is a test code that reproduces the problem:

template <typename T>
void test_alignment() {
    // allocate memory and record the original address
    unsigned char *origin;
    unsigned char *tmp = (unsigned char*)malloc(sizeof(unsigned short) + sizeof(T));
    origin = tmp;

    // push data with size of 2 bytes
    *((unsigned short*)tmp) = 1;
    tmp += sizeof(unsigned short);

    // attempt to push data of type T
    *((T*)tmp) = (T)1;

    // free the memory
    free(origin);
}

static void test_alignments() {
    test_alignment<bool>();
    test_alignment<wchar_t>();
    test_alignment<short>();
    test_alignment<int>();
    test_alignment<long>();
    test_alignment<long long>();   // fails on iPhone device
    test_alignment<float>();
    test_alignment<double>();      // fails on iPhone device
    test_alignment<long double>(); // fails on iPhone device
    test_alignment<void*>();
}

猜测,它必须是一个内存对齐的问题,我决定,我要彻底了解这个问题。从内存对齐,我的(有限)的理解时, TMP 得到由2个字节先进,它变得不对齐的数据类型的对齐大于2个字节:

Guessing that it must be a memory alignment issue, I decided I want to understand the problem thoroughly. From my (limited) understanding of memory alignment, when tmp gets advanced by 2 bytes, it becomes misaligned for data types whose alignment is greater than 2 bytes:

    tmp += sizeof(unsigned short);

但是测试code执行不行了 INT 和其他人!它不仅不能为长长双击长双

But the test code is executed alright for int and others! It only fails for long long, double and long double.

检查每个数据类型的大小和对齐透露,发生故障的数据类型具有不同的那些的sizeof __ alignof 值:

Examining the size and alignment of each data type revealed that the failing data types are the ones that have different sizeof and __alignof values:

iPhone 4:
bool           sizeof = 1 alignof = 1
wchar_t        sizeof = 4 alignof = 4
short int      sizeof = 2 alignof = 2
int            sizeof = 4 alignof = 4
long int       sizeof = 4 alignof = 4
long long int  sizeof = 8 alignof = 4 // 8 <> 4
float          sizeof = 4 alignof = 4
double         sizeof = 8 alignof = 4 // 8 <> 4
long double    sizeof = 8 alignof = 4 // 8 <> 4
void*          sizeof = 4 alignof = 4

iPhone Simulator on Mac OS X 10.6:
bool           sizeof = 1 alignof = 1
wchar_t        sizeof = 4 alignof = 4
short int      sizeof = 2 alignof = 2
int            sizeof = 4 alignof = 4
long int       sizeof = 4 alignof = 4
long long int  sizeof = 8 alignof = 8
float          sizeof = 4 alignof = 4
double         sizeof = 8 alignof = 8
long double    sizeof = 16 alignof = 16
void*          sizeof = 4 alignof = 4

(这些是从C ++数据比对和便携性

有人可以告诉我是什么引起的错误?区别 EXC_BAD_ACCESS 的真正原因?如果是这样,由什么机制?

Can someone enlighten me what's causing the error? Is the difference really the cause of EXC_BAD_ACCESS? If so, by what mechanics?

推荐答案

这其实很烦人,但不能太意外对于我们这些在pre-86世界买下了: - )

That's actually very annoying, but not so unexpected for those of us bought up in a pre-x86 world :-)

想到的(这是的纯粹的猜测)是编译器修复你的code,以确保数据类型正确对齐,但<$的唯一原因C $ C>的sizeof / alignof 不匹配导致问题。我似乎记得,ARM6架构放松一些规则对某些数据类型,但从来没有得到它很好看,因为在作出决定去与不同的CPU。

The only reason that comes to mind (and this is pure speculation) is that the compiler is "fixing" your code to ensure that the data types are aligned correctly but the sizeof/alignof mismatches are causing problems. I seem to recall that ARM6 architecture relaxed some of the rules for some data types but never got a good look at it because the decision was made to go with a different CPU.

(更新:这实际上是由寄存器的设置(因此可能是软件控制),所以我想即使是现代的CPU仍然可以恨恨地抱怨的偏差)。

我会做将看看生成的程序集的第一件事,看看如果编译器填充你的短,以对准下一个(实际)数据类型(这将是IM pressive)或(更可能)pre-填充写它之前的实际数据类型。

The first thing I would do would be to have a look at the generated assembly to see if the compiler is padding your short to align the next (actual) data type (that would be impressive) or (more likely) pre-padding the actual data type before writing it.

其次,找出实际的对齐要求都为Cortex A8的,我认为是什么iphone4的使用的核心。

Secondly, find out what the actual alignment requirement are for the Cortex A8 which I think is the core used in the IPhone4.

两种可能的解决方案:

1 /你可能需要每种类型强制转换为字符阵列和传送字符一次一个 - 这应该有希望避免对齐问题,但可能有性能影响。使用的memcpy 很可能是最好的,因为它无疑将是codeD利用底层的CPU已经(如传输4个字节的块,其中可能与一个 - 字节块的开始和结束)。

1/ You may have to cast each type into a char array and transfer the characters one at a time - this should hopefully avoid the alignment issues but may have a performance impact. Use of memcpy would probably be best since it will no doubt be coded to take advantage of the underlying CPU already (such as transferring four-byte chunks where possible with one-byte chunks at the start and end).

2 /对于那些不想经过,后补充足够的填充,以确保他们正确对齐。例如,是这样的:

2/ For those data types that don't want to be put immediately after a short, add enough padding after that short to ensure they align correctly. For example, something like:

tmp += sizeof(unsigned short);
tmp = (tmp + sizeof(T)) % alignof(T);

这应该提前 TMP 到下一个正确对齐的位置尝试存储值之前。

which should advance tmp to the next properly aligned location before attempting to store the value.

您需要做同样的读书回来后(我假设短则表示数据被存储,所以你可以告诉它是什么数据类型)。

You'll need to do the same reading it back later (I'm assuming the short is indicative of the data being stored so you can tell what data type it is).

把从OP的最终解决方案在答题的完整性(这样的人没有检查注释):

首先,装配(在X code,运行菜单&gt;调试器显示&GT;来源和拆卸)显示 STMIA处理8个字节的数据时指令时(即长长),而不是 STR 指令。

First, the assembly (on Xcode, Run menu > Debugger Display > Source and Disassembly) shows that the STMIA instruction is used when handling 8 bytes of data (i.e., long long), instead of the STR instruction.

接下来的ARM体系结构参考手册的ARMv7-A(相当于Cortex A8的架构)的部分A3.2.1未对齐的数据访问指出, STMIA 做不支持未对齐的数据访问,而 STR 并(根据某些注册表设置)。

Next, section "A3.2.1 Unaligned data access" of the "ARM Architecture Reference Manual ARMv7-A" (the architecture corresponding to Cortex A8) states that STMIA does not support unaligned data access while STR does (depending on certain registry settings).

所以,问题的大小长长和错位。

So, the problem was the size of long long and misalignment.

至于溶液,一炭在一次一工作时,作为起始

As for the solution, one-char-at-a-time is working, as a starter.

这篇关于为什么这个EXC_BAD_ACCESS用很长很长,而不是与诠释发生呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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