ego*_*ego 18 c memory-management strict-aliasing
为可变大小的数组分配内存时,我经常这样做:
struct array {
long length;
int *mem;
};
struct array *alloc_array( long length)
{
struct array *arr = malloc( sizeof(struct array) + sizeof(int)*length);
arr->length = length;
arr->mem = (int *)(arr + 1); /* dubious pointer manipulation */
return arr;
}
Run Code Online (Sandbox Code Playgroud)
然后我使用这样的arrray:
int main()
{
struct array *arr = alloc_array( 10);
for( int i = 0; i < 10; i++)
arr->mem[i] = i;
/* do something more meaningful */
free( arr);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这工作和编译没有警告.然而,最近我读到了严格的别名.根据我的理解,上面的代码在严格别名方面是合法的,因为通过它访问int *
的内存不是通过它访问的内存struct array *
.代码实际上是否违反了严格的别名规则?如果是这样,如何修改它们不破坏它们?
我知道我可以单独分配结构和数组,但是我也需要单独释放它们,大概是在某种free_array
功能中.这意味着我必须知道我释放它时释放的内存类型,这会使代码复杂化.它也可能会变慢.这不是我想要的.
dbu*_*ush 17
在结构中声明灵活数组成员的正确方法如下:
struct array {
long length;
int mem[];
};
Run Code Online (Sandbox Code Playgroud)
然后您可以像以前一样分配空间,而无需分配任何内容mem
:
struct array *alloc_array( long length)
{
struct array *arr = malloc( sizeof(struct array) + sizeof(int)*length);
arr->length = length;
return arr;
}
Run Code Online (Sandbox Code Playgroud)
Modern C官方支持灵活的阵列成员.因此,您可以按如下方式定义结构:
struct array {
long length;
int mem[];
};
Run Code Online (Sandbox Code Playgroud)
并像现在一样分配它,而不会增加可疑指针操作的麻烦.它将开箱即用,所有访问将正确对齐,您不必担心语言的黑暗角落.虽然,自然,如果你有一个是唯一可行的单,你需要分配这样的成员.
至于你现在拥有的,由于分配的存储没有声明的类型(它是一个空白的平板),你没有打破严格的别名,因为你没有给那个内存一个有效的类型.唯一的问题是可能会混淆对齐.虽然结构中的类型不太可能.
归档时间: |
|
查看次数: |
716 次 |
最近记录: |