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

所以我试图编写自己的'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*'

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

对我来说,在互联网上发现这一点是不可能的,因为每个人都在问如何在函数中更改全局变量。

我希望有人可以帮助我,因为否则我会很快烧毁我的房子。预先谢谢你。

蒂姆

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

快速摘要:

该错误实际上与您要执行的操作无关-实现malloc()

修复

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

完整答案

严格来说,这段代码

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

strict aliasing violation,可能违反了C标准的6.3.2.3 Pointers,p7

  

指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针未针对引用的类型正确对齐,则行为未定义。

您的错误

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.

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

但是

在这种情况下,您正在“尝试编写自己的'malloc'库”,并且实现中提供了malloc(),因此这些规则实际上并不适用因为您要提供 C实现本身的一部分

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

由于7.22.3 Memory management functions,他们无法这样做:

  

如果分配成功,则返回的指针将进行适当对齐,以便可以将其分配给具有基本对齐要求的任何类型的对象的指针,然后将其用于在分配的空间中访问此类对象或此类对象的数组

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

malloc()(以及calloc()和...)管理的内存以“ untyped”开头,但是在一致的C代码中不能有这样的“ untyped”内存。使用void *引用内存怎么办?您无法在符合C代码的void *指针上进行指针算术运算。而且您将必须执行指针算术来管理内存。因此,您几乎必须使用指向某种类型的指针来管理内存。

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

因此,您必须“键入”在malloc()实现中管理的内存,但是当malloc()调用将内存传递给调用方时,将违反严格的别名规则

如果您管理自己的存储权,您的malloc()实现将不会违反 6.3.2.3指针(第7页)的对齐限制。

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

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

本文链接:https://www.f2er.com/3143826.html

大家都在问