Rob*_*nes 1 c compiler-construction
在讨论中关于转换malloc许多人的返回值已声称隐式声明malloc会导致返回值被转换为int然后重新转换回T*可能导致在以下情况下截断指针:
sizeof(int) < sizeof(void*)
Run Code Online (Sandbox Code Playgroud)
这意味着编译器会执行以下操作:
malloc有人真的可以证明这发生了吗?在64位Linux上使用一些示例代码说?
我自己做,但我无法访问64位机器.
描述发生的事情的问题在步骤2中.使用隐式声明,调用站点的代码实际上不会"转换"函数的返回值.
会发生的是,调用站点的代码通过假设它的类型为"int"来提取返回值(通常来自寄存器或堆栈外).对于不同的操作系统和编译器,执行此操作的过程是不同的,并且通常由ABI文档指定.
对于最常见的ABI,int和void*的返回位置和大小是相同的,所以即使它不正确,你实际上也不会有任何问题.对于32位和64位平台上的Linux,Windows和Mac OS X 都是如此,我相信 32位平台.
在64位平台上,"long"和"void*"更常见的是相同的大小,因此如果你有一个malloc()的隐式声明,返回值将被截断.但是,有几种流行的64位编程模型.
回到DOS开发的"美好时光",可以创建以"int"为16位,指针为32位(实际为24位)的模式运行的程序.在这些情况下,使用隐式原型调用malloc()会截断返回的值.
请注意,即使在截断返回值的情况下,您仍可能没有运行时问题,具体取决于该值是否实际超出int的有效范围.
在Mac OS X上,在64位模式下,此代码:
#include <stdio.h>
int main (int argc, const char * argv[]) {
int x = malloc(128);
void *p = malloc(128);
printf("Hello, World!\nsizeof(int)=%d,sizeof(void*)=%d,x=0x%xd,p=%p\n", sizeof(int), sizeof(void *), x, p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
打印:
你好,世界!的sizeof(INT)= 4,的sizeof(无效*)= 8,X = 0x1001c0d,P = 0x100100240
请注意,"x"值的位数少于"p"值,而是静默地删除了值的最高32位.两次调用malloc时的实际汇编代码如下所示:
LM2:
movl $128, %edi
call _malloc
movl %eax, -12(%rbp)
LM3:
movl $128, %edi
call _malloc
movq %rax, -8(%rbp)
Run Code Online (Sandbox Code Playgroud)
因此,malloc(在%rax中)返回了正确的值,但是当movl指令被移动到变量"x"时,它会截断它.