以下C代码将导致传递0xFFFFFFFFFFFFFFFF
到malloc()
而不是预期的0,由Visual Studio 2013编译为64时:奇怪代码2013
#include <stdlib.h>
int main(int argc, char *argv[]) {
int x = -1;
void *p = malloc(x + 1);
}
打开拆卸视图揭示了这种奇怪的片断(调试配置,虽然推出在功能上是相同的):
; 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
我犹豫称这是一个代码生成错误。我必须认为这是我错过的东西。但是,我从来没有见过这种情况,它肯定会产生不正确的行为。
这是怎么发生的?
'main'应该返回'int',而不是'void'。我在clang中看到了一些使'char'始终未被签名的选项。也许你的'int'会发生同样的情况,但我不确定。 – ForceBru
那么,它是实现定义是否[m/c/re] alloc(0)'返回NULL或无法取消引用的有效指针。这可能是Visual Studio将'SIZE_MAX'传递给'malloc()'以确保分配失败,在这种情况下返回NULL。 – EOF
https://msdn.microsoft.com/en-us/library/jj161081.aspx –