gpt4 book ai didi

c - malloc 返回类型转换困惑

转载 作者:太空宇宙 更新时间:2023-11-04 05:37:18 25 4
gpt4 key购买 nike

我正在浏览 here并发现如果我们不包含 stdlib.h、转换返回值以及指针和整数大小在系统上不同,malloc 可能会导致不需要的行为。

下面是该 SO 问题中给出的代码片段。这是在指针和整数大小不同的 64 位机器上尝试的。

int main()
{
int* p;
p = (int*)malloc(sizeof(int));
*p = 10;
return 0;
}

如果我们不包含 stdlib.h,编译器将假定 malloc 返回类型为 int,并将其转换并分配给不同的大小指针可能会导致不需要的行为。 但我的问题是为什么将 int 转换为 int* 并将其分配给不同大小的指针会导致问题。

最佳答案

int main()
{
int* p;
p = (int*)malloc(sizeof(int));
*p = 10;
return 0;
}

在 C99 和 C2011 规则下,调用 malloc没有可见的声明是违反约束,这意味着符合标准的编译器必须发出诊断。 (这与 C 所说的某事是“非法的”差不多。)如果您的编译器没有对调用发出警告,您应该找出使用什么选项来让它发出警告。

在 C90 规则下,调用没有可见声明的函数会导致编译器假定该函数实际上返回类型为 int 的结果。 .自 malloc实际上是用 void* 的返回类型定义的,行为未定义;编译器不需要对其进行诊断,但标准完全没有说明调用被评估时会发生什么。

实践中通常发生的情况是编译器生成代码好像 malloc被定义为返回 int结果。例如,malloc可能会把它的 64 位 void*导致某些特定的 CPU 寄存器,并且调用代码可能假设该寄存器包含一个 32 位 int . (这不是类型转换;它只是错误的代码,错误地将一种类型的值视为另一种类型。)那个(可能是垃圾)int然后值转换int*并存储在 p .您可能丢失返回指针的高位 低位 32 位——但这只是它可能出错的任意多种方式中的一种。

malloc可能会将其 64 位结果压入堆栈,而调用者可能只会从堆栈弹出 32 位,从而导致堆栈未对齐,从而导致所有后续执行不正确。由于历史原因,C 编译器通常不使用这种调用约定,但标准允许这样做。

如果int , void* , 和 int*所有的大小恰好相同(因为它们通常在 32 位系统上),代码可能会工作——但即使这样也不能保证。例如,调用约定可能使用一个寄存器返回 int结果和一个不同的返回指针结果。同样,大多数现有的 C 调用约定都允许旧的错误代码做出这样的假设。

调用 malloc需要 #include <stdlib.h> ,即使某些编译器可能不强制执行该要求。添加 #include 更容易(并放弃 Actor )而不是花时间思考如果你不这样做会发生什么。

关于c - malloc 返回类型转换困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30417052/

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