当Visual Studio 2013为x64编译时,以下C代码将导致0xFFFFFFFFFFFFFFFF
传递给malloc()
而不是预期的0:
#include <stdlib.h>
int main(int argc, char *argv[]) {
int x = -1;
void *p = malloc(x + 1);
}
打开反汇编视图会显示这个奇怪的片段(Debug配置,虽然Release在功能上是相同的):
; int x = -1;
mov dword ptr [x],0FFFFFFFFh
; void *p = malloc(x + 1);
mov eax,dword ptr [x]
add eax,1
mov eax,eax
mov rcx,0FFFFFFFFFFFFFFFFh
cmovb rax,rcx
mov rcx,rax
call qword ptr [__imp_malloc (07F79C80B228h)]
mov qword ptr [p],rax
转换为size_t不会改变任何内容,但将结果存储到临时变量然后将其传递给malloc()将会。
奇怪的是,当调用类似声明的任何其他函数时,这不会发生:
void * __cdecl foo(size_t y) {
return NULL;
}
int main(int argc, char *argv[]) {
int x = -1;
void *p = foo(x + 1);
}
在这种情况下,会生成正确的代码(请注意缺少的cmovb
内容):
; int x = -1;
mov dword ptr [x],0FFFFFFFFh
; void *p = foo(x + 1);
mov eax,dword ptr [x]
inc eax
cdqe
mov rcx,rax
call foo (07F6AB84100Ah)
mov qword ptr [p],rax
我毫不犹豫地将此称为代码生成错误。我必须假设它是我缺少的东西。但是,我以前从未见过它,它肯定会产生不正确的行为。
为什么会这样?
答案 0 :(得分:2)
它可以防止整数溢出(在评论here中引用)。
如果传递给malloc
的值是整数溢出(有符号或无符号)的结果,而不是让程序分配的内存少于编译器认为预期的内存,则会最大化表达式并尝试分配这一点。