首页
社区
课程
招聘
[讨论]是否是编译器无中生有的代码
发表于: 2023-7-30 21:55 4027

[讨论]是否是编译器无中生有的代码

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模式下,就可能是随机值。今天本文的分析似乎也在印证着这一说法。不过究竟是否是这样,我也不能确认,如有大佬路过,不妨赐教一二。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 4939
活跃值: (2851)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
 变量 或 对象 创建时,必须初始化, 这是编程的基本原则。 没初始化可以认为是随机值, 具体值看编译器的想法了。
2023-7-31 16:58
0
游客
登录 | 注册 方可回帖
返回
//