严格别名和存储位置 [英] Strict aliasing and memory locations

查看:119
本文介绍了严格别名和存储位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

严格别名prevents我们使用不兼容的类型访问同一存储位置。

Strict aliasing prevents us from accessing the same memory location using an incompatible type.

int* i = malloc( sizeof( int ) ) ;  //assuming sizeof( int ) >= sizeof( float )
*i = 123 ;
float* f = ( float* )i ;
*f = 3.14f ;

这将根据C标准是非法的,因为编译器知道 INT 不能用浮法访问左值。

如果我使用的指针指向正确的内存,这样的:

What if I use that pointer to point to correct memory, like this:

int* i = malloc( sizeof( int ) + sizeof( float ) + MAX_PAD ) ;
*i = 456 ;

首先,我分配内存 INT 浮动最后的部分是内存,这将使浮动将存储在对齐的地址。 浮动要求对4 MAX_PAD倍数对齐是取决于系统通常是16的8个字节。在任何情况下, MAX_PAD 是足够大,以便浮动可正确对齐。

First I allocate memory for int, float and the last part is memory which will allow float to be stored on aligned address. float requires to be aligned on multiples of 4. MAX_PAD is usually 8 of 16 bytes depending on the system. In any case, MAX_PAD is large enough so float can be aligned properly.

然后我写了 INT I ,到目前为止好。

Then I write an int into i, so far so good.

float* f = ( float* )( ( char* )i + sizeof( int ) + PaddingBytesFloat( (char*)i ) ) ;
*f= 2.71f ;

我使用指针 I INT 的规模递增,并与函数正确对齐 PaddingBytesFloat(),它返回来对齐浮动所需的字节数,提供的地址。然后,我写了一个浮动进去。

I use the pointer i, increment it with the size of int and align it correctly with the function PaddingBytesFloat(), which returns the number of bytes required to align a float, given an address. Then I write a float into it.

在这种情况下,˚F点不重合的不同的存储器位置;它有不同的类型。

In this case, f points to a different memory location that doesn't overlap; it has a different type.

结果
下面是标准的某些部分(ISO / IEC 9899:201X)6.5,我靠写这个例子时


Here are some parts from the standard (ISO/IEC 9899:201x) 6.5 , I was relying on when writing this example.

混叠是当多个左值指向同一个存储单元。标准要求,那些左值具有兼容类型的有效对象的类型。

Aliasing is when more than one lvalue points to the same memory location. Standard requires that those lvalues have a compatible type with the effective type of the object.

什么是有效的类型,从标准的报价:

What is effective type, quote from standard:

用于向它的存储值的访问的有效类型的一个目的是的声明类型
对象,如果any.87)如果一个值存储到一个对象不具有声明的类型通过
左值具有类型不字符类型,则左值的类型成为
对于访问和不修改后续访问有效类型的对象的
所存储的值。如果值被复制到一个对象具有不使用声明的类型
的memcpy或的memmove,或者被复制为字符类型的阵列,则有效类型
对于访问和对不修改的后续访问修改的对象的
值是有效类型从该值被复制,如果有对象的。对于所有其他的访问不具有声明类型的对象中,有效的对象的类型是
简单地用于接入左值的类型。

87)分配的对象没有声明的类型。

我试图连接件,如果这是允许搞清楚。在我的帧间pretation有效类型的分配对象可以根据在该存储器使用的左值的类型而改变,因为这部分:对于
所有其他的访问不具有声明类型的对象中,有效的对象的类型是简单地用于接入左值的类型。

I'm trying to connect the pieces and figure out if this is allowed. In my interpretation the effective type of an allocated object can be changed depending on the type of the lvalue used on that memory, because of this part: For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

这是合法的吗?如果不是,如果我用一个空指针作为左值,而不是在我的第二个例子一个int指针 I ?如果连那就没办法了,如果我拿到了地址,该地址分配给浮动指针在第二个例子,作为一个memcopied值,该地址是从来没有用作左值了。

Is this legal? If not, what if I used a void pointer as lvalue instead of an int pointer i in my second example? If even that wouldn't work, what if I got the address, which is assigned to the float pointer in the second example, as a memcopied value, and that address was never used as an lvalue before.

推荐答案

我认为是的,这是合法的。

I think that yes, it is legal.

要说明我的观点,让我们来看看code:

To illustrate my point, let's see this code:

struct S
{
    int i;
    float f;
};
char *p = malloc(sizeof(struct S));

int *i = p + offsetof(struct S, i);  //this offset is 0 by definition
*i = 456;
float *f = p + offsetof(struct S, f);
*f= 2.71f;

这code是,国际海事组织,明确合法的,就相当于你从一个编译点,为() PaddingBytesFloat的合适值和 MAX_PAD

This code is, IMO, clearly legal, and it is equivalent to yours from a compiler point of view, for appropriate values of PaddingBytesFloat() and MAX_PAD.

请注意,我的code不使用类型的struct ,它只是用来缓解填补处理的任何计算L值。

Note that my code does not use any l-value of type struct S, it is only used to ease the calculation of the paddings.

当我读到的标准,malloc分配内存也没有声明的类型,直到事情是有写的。随后声明的类型是什么写入。因此,这样的内存声明的类型可以随时更改,覆盖不同类型的值的内存,很像一个工会。

As I read the standard, in malloc'ed memory has no declared type until something is written there. Then the declared type is whatever is written. Thus the declared type of such memory can be changed any time, overwriting the memory with a value of different type, much like an union.

TL; DR:我的结论是,与动态内存你是安全的,对于严格走样只要你阅读使用相同类型(或兼容),你用它来最后一次写入到内存内存

TL; DR: My conclusion is that with dynamic memory you are safe, with regard to strict-aliasing as long as you read the memory using the same type (or a compatible one) you use to last write to that memory.

这篇关于严格别名和存储位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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