C --- 全局变量声明(重新定义)的问题

C --- Problems with declaration (redefinition) of global variables

所以我正在尝试编写自己的 'malloc' 库,但我的全局变量有问题。

在下面的代码中,您可以看到,我正在创建一个 int 指针来将一个整数写入 char 数组,并且该 int 指针指向我的 char 数组的第一个字节,认为它是内存一个整数。

char myMemory[1048576];

int* pMem = (int*)(&myMemory[0]);
*pMem = (1048576-5);
myMemory[4] = 'f';

//... and so forth

对于最后一行,我收到以下错误消息:

redefinition of 'myMemory' with a different type 'int [4]' vs 'char [1048576]'

对于 *pMem = (...); 我得到以下内容

invalid operands to binary expression 'int*' and 'int*'

也许我不允许全局更改全局变量,当我在测试函数中执行相同的操作时一切正常。

我不可能在互联网上找到它,因为每个人都在问如何更改函数中的全局变量,这是..

我希望有人能帮我解决这个问题,否则我很快就会烧掉我的房子。提前谢谢你。

蒂姆

快速总结:

该错误确实不适用于您要执行的操作 - 实施 malloc()

修复

使用不会给您 redefinition of 'myMemory' with a different type 'int [4]' vs 'char [1048576]' 错误的编译器或编译器参数。

完整答案

严格来说,这段代码

int* pMem = (int*)(&myMemory[0]);

是C标准的strict aliasing violation and potentially violates 6.3.2.3 Pointers, p7

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.

你的错误

redefinition of 'myMemory' with a different type 'int [4]' vs 'char [1048576]'

是因为您违反了严格的别名规则。

一般来说,在 C 中,您不能将没有开始的内存视为具有特定类型并将其视为具有另一种类型 - 除了您始终可以将任何内存视为 char 类型.例如,您不能将 char 数组视为 int 数组。

这是严格的别名规则。

但是您可以采用 int 数组并将其视为 char 数组 - 或 signed charunsigned char 数组。

即使内存以某种方式开始为 int 但你所拥有的只是一个指向它的 char 指针(或 void 指针),当你将它投回去并作为 int 访问它,内存必须与您所在的平台正确对齐。

您的代码可能会或可能不会这样做 - 在您实际 运行 之前您无法确定。如果它不满足对齐要求,您可能会遇到 SIGBUS 或其他一些失败 - like this.

违反任何这些规则都会导致未定义的行为。

但是

在这种情况下,您是 "trying to write [your] own 'malloc' library",并且 malloc() 由实施提供,因此这些规则并不真正适用,因为您'重新提供 C 实现本身的一部分

为什么?为什么这些规则不适用于 C 环境本身的实现?

他们不能,因为 7.22.3 Memory management functions:

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated

您根本无法在严格符合 C 代码中做到这一点。

malloc()(以及 calloc() 和 ...)管理的内存以 "untyped" 开头,但您不能在符合 C 代码的情况下拥有这样的 "untyped" 内存.使用 void * 引用内存怎么样?您不能在符合 C 代码的 void * 指针上进行指针运算。你将不得不进行指针运算来管理内存。所以你几乎必须使用指向某种类型的指针来管理内存。

并且您不能使用数组来避免此类指针运算,因为这些数组还必须具有具体类型。

因此您必须 "type" 您在 malloc() 实现中管理的内存,但是当该内存作为 malloc() 调用的结果传递给调用者时,严格违反了别名规则。

如果您正确管理内存,您的 malloc() 实现将不会违反 6.3.2.3 指针、第 7 页的对齐限制。

为什么这么多代码违反了这些规则?

因为大多数编写代码的人使用的 x86 平台对未对齐的访问极度宽容