-
-
[讨论]是否是编译器无中生有的代码
-
发表于:
2023-7-30 21:55
4027
-
接下来分析的问题,不太确认是否是编译器无中生有的代码。
C++源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class GameState2
{
private :
GameState2* nextState_;
public :
GameState2() {};
virtual ~GameState2() { };
};
class GameOver2 : public GameState2
{
public :
GameOver2() {};
};
GameOver2* pGameOver2 = new GameOver2;
|
这两天一直在读类似上面调用方式的反汇编代码:
1 2 3 4 5 6 7 8 9 10 | 00407E80 6A 08 push 8
00407E82 E8 4C 19 00 00 call operator new ( 04097D3h )
00407E87 83 C4 04 add esp, 4
00407E8A 89 45 D0 mov dword ptr [ebp - 30h ],eax
00407E8D C7 45 FC 00 00 00 00 mov dword ptr [ebp - 4 ], 0
00407E94 83 7D D0 00 cmp dword ptr [ebp - 30h ], 0
00407E98 74 17 je 0407EB1h
00407E9A 6A 08 push 8
00407E9C 8B 4D D0 mov ecx,dword ptr [ebp - 30h ]
00407E9F E8 7C AB FF FF call std::_Uninitialized_backout_al<std::allocator<sf::RectangleShape> >::__autoclassinit2 ( 0402A20h )
|
一直无法理解,为什么在new之后会出现一个memset(通过IDA可以确定最后一个call是封装的memset)的功能函数。搜索源代码也没有发现GameOver2相关的实现有memset函数。直到今天尝试用release优化模式/O2编译之后发现其对应的反汇编代码为:
1 2 3 4 5 | 90 : GameOver2 * pGameOver2 = new GameOver2;
0040404B 6A 08 push 8
0040404D E8 FE 05 00 00 call operator new ( 0404650h )
00404052 89 45 E0 mov dword ptr [ebp - 20h ],eax
00404055 0F 57 C0 xorps xmm0,xmm0
|
可以看到并没有memset功能函数。
结论:
很久之前知道一个说法,变量在Debug模式下编译,即使没有对变量赋初值,也会被使用0值作为初始化,但是Release模式下,就可能是随机值。今天本文的分析似乎也在印证着这一说法。不过究竟是否是这样,我也不能确认,如有大佬路过,不妨赐教一二。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!