gpt4 book ai didi

c - 是否可以在不违反严格别名的情况下将字符数组用作内存池?

转载 作者:行者123 更新时间:2023-12-04 07:39:56 24 4
gpt4 key购买 nike

我有一个静态分配的字符数组。我可以在不违反严格的别名规则的情况下重用这个数组来存储不同的类型吗?我不太了解严格的别名,但这是一个执行我想做的代码示例:

#include <stdio.h>

static char memory_pool[256 * 1024];

struct m1
{
int f1;
int f2;
};

struct m2
{
long f1;
long f2;
};

struct m3
{
float f1;
float f2;
float f3;
};

int main()
{
void *at;
struct m1 *m1;
struct m2 *m2;
struct m3 *m3;

at = &memory_pool[0];

m1 = (struct m1 *)at;
m1->f1 = 10;
m1->f2 = 20;

printf("m1->f1 = %d, m1->f2 = %d;\n", m1->f1, m1->f2);

m2 = (struct m2 *)at;
m2->f1 = 30L;
m2->f2 = 40L;

printf("m2->f1 = %ld, m2->f2 = %ld;\n", m2->f1, m2->f2);

m3 = (struct m3 *)at;
m3->f1 = 5.0;
m3->f2 = 6.0;
m3->f3 = 7.0;

printf("m3->f1 = %f, m3->f2 = %f, m3->f3 = %f;\n", m3->f1, m3->f2, m3->f3);

return 0;
}
我使用 gcc 和 -Wstrict-aliasing=3 -fstrict-aliasing 编译了这段代码,它按预期工作:
m1->f1 = 10, m1->f2 = 20;
m2->f1 = 30, m2->f2 = 40;
m3->f1 = 5.000000, m3->f2 = 6.000000, m3->f3 = 7.000000;
那个代码安全吗?假设 memory_pool总是足够大。

最佳答案

Is it possible to use a character array as a memory pool without violating strict aliasing?


不,C 2018 6.5 7 中的规则说对象定义为 char 的数组可以访问为:
  • char 数组兼容的类型,
  • char 数组兼容的类型的限定版本,
  • char 的数组对应的有符号或无符号类型的类型,
  • char 的数组对应的有符号或无符号类型的类型,
  • 包含 char 数组的聚合或 union 类型在其成员中,或
  • 一种字符类型。
  • char 的数组不能使用 3 和 4 ;它们仅适用于原始类型是整数类型的情况。在您的各种结构示例中,结构与 char 的数组不兼容。 (也不是他们的成员),排除 1 和 2。他们不包括 char 的数组在他们的成员中,排除5个。他们不是字符类型,排除6个。

    I've compiled this code using gcc with -Wstrict-aliasing=3 -fstrict-aliasing, and it works as intended:


    示例输出显示代码在一次测试中产生了所需的输出。这不等于显示它按预期工作。

    Is that code safe?


    不可以。在某些情况下可以使代码安全。首先,以适当的对齐方式声明它,例如 static _Alignas(max_align_t) memory_pool[256 * 1024]; . ( max_align_t<stddef.h> 中定义。)这使得指针转换部分定义。
    其次,如果您使用 GCC 或 Clang 并请求 -fno-strict-aliasing ,编译器提供了对 C 语言的扩展,放宽了 C 2018 6.5 7。或者,在某些情况下,可以从编译器和链接器设计的知识中推断出即使违反了 6.5 7,您的程序也可以工作:如果程序在单独的翻译单元中编译,并且目标模块不包含类型信息或没有使用花哨的链接时优化,并且在实现内存池的翻译单元中没有出现别名违规,那么违规不会产生不良后果6.5 7 因为 C 实现无法区分内存池方面违反 6.5 7 的代码和不违反 6.5 7 的代码。此外,您必须知道指针转换按预期工作,它们有效地生成指向相同地址的指针(而不仅仅是可以转换回原始指针值但不能直接用作指向同一内存的指针的中间数据) .
    没有不良后果的推论是脆弱的,应谨慎使用。例如,在实现内存池的翻译单元中很容易意外违反 6.5 7,例如通过将指针存储在已释放的内存块中或将大小信息存储在已分配 block 之前的隐藏 header 中。

    关于c - 是否可以在不违反严格别名的情况下将字符数组用作内存池?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67543596/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com