bug_ex.c
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <stdio.h>
void bug2(void *a,void *b,uint64_t offset,uint64_t size,void *fp,int ver)
{
printf("fp:%p\n",fp);
}
bug.c
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <stdio.h>
void bug1(void *a,void *b,uint64_t offset,uint64_t size,void *fp,int ver)
{
printf("fp:%p\n",fp);
}
int main()
{
void *a = malloc(1);
void *b = malloc(1);
void *fp = malloc(1);
off_t offset = 1;
size_t size = 1;
bug1(a,b,offset,size,fp,1);
bug2(a,b,offset,size,fp,1);
free(a);
free(b);
free(fp);
return 0;
}
Makefile
all:bug bug.asm
bug.asm:bug
objdump -SD bug >bug.asm
bug:bug.o bug_ex.o
gcc -g -o bug bug.o bug_ex.o
bug.o:bug.c
gcc -g -D_FILE_OFFSET_BITS=64 -c bug.c
bug_ex.o:bug_ex.c
gcc -g -D_FILE_OFFSET_BITS=64 -c bug_ex.c
clean:
rm -f bug.o bug_ex.o bug bug.asm
我在ubuntu11.10,gcc 4.6.1上make编译后执行后
./bug
fp:0x80ea028
fp:0x1
bug.c调用函数bug2时,由于没有函数原型(也就是函数成名)编译器不知道函数的参数的具体类型,就按照实际参数的类型调用函数(也就是把参数入栈)也就是
a,b,offset,size,fp,1
类型为
void *, void *, off_t, size_t, FILE *, int
其中第4个实参的类型(size_t)与形参(int64_t)的类型不一致,在32为系统上
size_t是32位的,调用的时候按32位入栈(少了4字节),所以bug2里取参数fp的时候其实取到的是ver的值(1)
实际压栈情况 取参数情况
---------- ----------
| a | | a | 栈顶
---------- ----------
| b | | b |
---------- ----------
| offset | | offset |
---------- ----------
| offset | | offset |
---------- ----------
| size | | size |
---------- ----------
| fp | | size |
---------- ----------
| ver | | fp |
---------- ----------
| xxxx | | ver |
---------- ----------
调用bug2时栈的状态