C++强制转换不同声明或类型的函数指针隐患

本文探讨了在使用函数指针时类型不匹配的问题,并通过一个具体的例子展示了不当的类型转换可能导致的不确定行为。深入分析了编译原理及运行时的表现,强调了正确类型检查的重要性。

之前碰到一个问题,没有注意看函数指针的定义。造成一个错误,写到这里给自己一个提醒。也给大家看看我这个不小心的人犯的错误。嘿嘿!

先看段测试代码:

void test( int param )
{
int ret = 0;
for ( int i = 0; i < param; ++i )
{
ret += i;
}

ret >>= 16;
ret |= ( ret << 16 );
}

typedef bool ( *PFUNC )( int args );

int main( void )
{
PFUNC Func;
Func = ( PFUNC )test;

if ( Func( 200 ) )
{
cout << "good" << endl;
}
else
{
cout << "bad" << endl;
}

return 0;
}

这段代码里面,我故意把test函数里面的内容多写几步,让它有“效果”。在游戏程序里面,一个函数可能有很多的语句,这里只是简单演示下我的错误- -。我们的函数指针声明是:

typedef bool ( *PFUNC )( int args );

它指向的是返回值为bool,参数为int类型的函数。而我定义的test函数是没有返回值的。来看看程序输出会是什么。

这里可以说,输出的结果是未知的。因为不知道Func( 200)的返回值是多少。可能有的朋友会疑问,这里的test函数不是没有返回值吗?

这里就要牵涉到汇编层面我们的返回值如果是在32位以内的话,都会放到eax里面。我们没有返回值,而通过强制类型转换。这里能通过编译了。但是在test函数结束时,eax寄存器里面的值是不确定的。当我们判断

if ( Func( 200 ) )这个条件也就是不确定的。在游戏程序中,这样的错误是不允许的。也可以说是严重的。

可能也有朋友会问为什么EAX的值是不确定的呢? 因为eax是通用寄存器,在函数内部,它通常用来保存一些临时值。所以改变的因素就很大。不确定性也就很大。

看看test的调试版本反汇编代码:

test:
004170B0 push ebp
004170B1 mov ebp,esp
004170B3 sub esp,0D8h
004170B9 push ebx
004170BA push esi
004170BB push edi
004170BC lea edi,[ebp-0D8h]
004170C2 mov ecx,36h
004170C7 mov eax,0CCCCCCCCh
004170CC rep stos dword ptr [edi]
004170CE mov dword ptr [ret],0
004170D5 mov dword ptr [i],0
004170DC jmp test+37h (4170E7h)
004170DE mov eax,dword ptr [i]
004170E1 add eax,1
004170E4 mov dword ptr [i],eax
004170E7 mov eax,dword ptr [i]
004170EA cmp eax,dword ptr [param]
004170ED jge test+4Ah (4170FAh)
004170EF mov eax,dword ptr [ret]
004170F2 add eax,dword ptr [i]
004170F5 mov dword ptr [ret],eax
004170F8 jmp test+2Eh (4170DEh)
004170FA mov eax,dword ptr [ret]
004170FD sar eax,10h
00417100 mov dword ptr [ret],eax
00417103 mov eax,dword ptr [ret]
00417106 shl eax,10h
00417109 or eax,dword ptr [ret]
0041710C mov dword ptr [ret],eax
0041710F pop edi
00417110 pop esi
00417111 pop ebx
00417112 mov esp,ebp
00417114 pop ebp
00417115 ret

改变eax的地方我已经标注为红色,我们能准确知道最后改变后的eax的值吗? 主函数里面还等着这个eax的值呢 - -

答案是不能,况且在复杂的游戏服务器程序中。这里只是单是返回值不同。还有参数不同的强制类型转换,参数和返回值都不同的强制类型转换。这种不小心的操作,很可能导致程序越界,溢出等而崩溃。

希望大家不要像我这么粗心哈。 嘿嘿。睡觉。。真睡了- -

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值