首页 > 解决方案 > C 中的严格别名违规以及如何编写符合要求的代码?

问题描述

下面看到的代码是在某些 arena 实现中看到的典型代码。可以在此处找到一个这样的示例(有关示例 impl. 的博客文章)。

#include<stdio.h>
#include<stdint.h>
#include<stdalign.h>

struct thing {
  int a;
  int b;
};

char buffer[128];

int main () 
{
  
  uintptr_t p1 = (uintptr_t)buffer;
  if (p1 % alignof(struct thing)) return 1;

  struct thing *t1 = (void*)buffer;
  t1->a = 10;
  t1->b = 20;
  
  uintptr_t p2 = (uintptr_t)(buffer + sizeof(struct thing));
  if (p2 % alignof(struct thing)) return 1;

  struct thing *t2 = (void*)(buffer + sizeof(struct thing));
  t2->a = 30;
  t2->b = 40;
  

  printf("%d\n",t1->a);   
  printf("%d\n",t2->a);   

  return 0;
}

编辑的代码:如果任何指针缺少正确对齐,则使程序返回 1

  1. 这是一个严格的混叠违规的实例,并且......
  2. 是将此类结构放置在缓冲区中并检索安全以使用指向该结构的指针的唯一方法,例如:

struct thing *t1 = memcpy(buffer,&((struct thing){10,20}),sizeof(struct thing));

标签: c

解决方案


问题在于,按照标准,只能以这种方式使用动态内存。

第 5 条表达式说(C11 的参考 n1570):

§6 访问其存储值的对象的有效类型是对象的声明类型,如果有的话。

如果您使用:

void * buffer = malloc(128);

那么 buffer 保证具有与任何标准类型兼容的对齐方式并且没有声明的类型

在这种情况下,您可以安全地将thing对象存储在缓冲区中,而不会触发任何严格的别名违规。但是在您的示例代码中,buffer声明的类型是char. 无论对齐方式如何,使用不同的类型都是严格的别名违规。


推荐阅读