编译50字节代码耗费4G内存

开发 项目管理
想用宏和内联汇编做些邪恶的事情(仅仅试着做一些怪异的测试,目的无关紧要),我决定写个程序让Vistual Studio的C++编译器分配4GB的内存,然后处于卡死状态。写个50字节的代码就可以了。

想用宏和内联汇编做些邪恶的事情(仅仅试着做一些怪异的测试,目的无关紧要),我决定写个程序让Vistual Studio的C++编译器分配4GB的内存,然后处于卡死状态。

写个50字节的代码就可以了。

一开始我可能没注意到我的机子并没有4GB的空闲内存,疯狂的数据分页,需要找到4GB的内存,使得我的笔记本在几分钟内都毫无反应。如果你的机子有超过4GB的空闲内存,使用ETW做内存分析倒是个很好的测试,看看你可以复现我的结果吗?

我简化了代码,只留下的最基本的精华部分,只是觉得这样很好玩:

  1. void test() 
  2.     __asm { add eax 
  3.     __asm { add eax 

这是编译器的输出:

  1. error C2414: illegal number of operands 
  2. error C2414: illegal number of operands 
  3. error C2400: inline assembler syntax error in ‘opcode’; found ‘end of file’ 
  4. fatal error C1060: compiler is out of heap space 

 

我是在Windows 64位上运行的,编译器是32位的大型地址进程,所以堆空间耗尽意味着分配大约4GB的内存空间。我连续进行多次编译,可以看出每次4GB的内存使用量都在飙升。

我很好奇,到底是哪部分编译程序在分配这些内存。我使用cl.exe编译器,用etwheap.bat记录了所有的堆空间和 VirtualAlloc 分配 ,并再次编译了源文件。事实证明我本应该使用wprui’s VAlloc Usage选项去获取追踪。仅仅只有几MB是从堆上分配的,大部分都是使用VirtualAlloc来分配的,如图所示:

接下来,为了完成调查,我查看了所有的调用栈。我们可以看到内联汇编程序的语法分析器正在使用它自己的VirtualHeap分配大量的Asm Tokens。VirtualHeap::Create 预留内存空间,VirtualHeap::HeapExtend提交内存。再深入研究下(没有显示)发现内存空间预留在512KB的内存块,被提交在 32KB的内存块。

还有一些细节,不是很清楚,像为什么VirtualHeap::HeapExtend调用 VirtualHeap::Create,但是却没有源代码,难以得知。

所以我们不再探究了,我像往常一样将把这个问题提交给VC++团队。如果他们解决了这个问题,我并不惊讶,这也算不上是一个严重的问题。第一次遇到这个问题时,因为我的机子没有4GB的空闲内存,所以才注意到它。

编译器是32位进程也是件好事儿,要不然它还会继续消耗内存,将远远超过4GB。条件限制万岁!

这些测试都是在VC++ 2010 的调试版本上进行的,我没试过其他版本。

 Linux 变体

还有一个很类似的问题(链接器在一个很简单的程序上消耗了大量内存,详情见 栈溢出)。

Windows 糟透了?

我预料到有人会说Windows太烂了,这就是为什么当遇到这个问题时,我的笔记本几分钟内都毫无反应。但是如果在Linux和OSX系统上分配 (或写入)4GB的内存,并不会引发严重的系统延迟问题,但其实这说明不了什么。我的笔记本只有8GB的内存,大部分都在被使用,想获取到空闲的4GB内 存的唯一可能的办法就是把大量的数据写到磁盘上。笔记本的硬盘相当慢,如果我是在工作机子上(32GB的内存,20GB可用)或者当笔记本上只有很少的程 序在运行时(5GB空闲内存),做同样的测试,4GB内存的分配和释放不到5秒中就可以完成。

Reddit的讨论链接在这儿。

额外补充

很奇怪,怎么会有一些博客文章比其他人的更受欢迎…

有人在复现这个问题时遇到了困难,这个bug只能确定在VS2010 SP1 出现,并且test函数放在源文件的最后。

这显然不是一个严重的bug—代码也有缺陷,编译器有给出了警告并且指出问题所在,也没出现什么大问题。但是它的确是一个失败的词法分析程序。尤其 是,内存不足会阻止VC++去报告一些括号不匹配的问题—假如你在test函数之后再添加一个函数,词法分析完成后,额外的警告就会显示出来了。

编译错误代码时给出出错的信息提示是很重要的,这也是Clang的显式设计目标之一。

在 Visual Studio SP1 中复现这个 Bug 了。见下图或查看原图。

原文链接:http://randomascii.wordpress.com/2013/08/14/50-bytes-of-code-that-took-4-gb-to-compile/

译文链接:http://blog.jobbole.com/46106/

责任编辑:陈四芳 来源: 伯乐在线
相关推荐

2012-07-02 16:55:48

4G

2013-01-30 09:25:21

4G通信网络LTE

2021-01-10 21:13:21

4G5GLTE技术

2017-08-01 08:28:46

4G服务器MySQL

2012-05-02 15:10:08

华硕笔记本

2021-05-10 10:16:03

5G4G网络

2011-09-29 10:13:30

4G3G

2009-06-09 10:34:41

802.16mLTE4G

2013-12-02 14:15:35

4G移动

2011-10-19 08:08:20

LTE

2011-04-29 17:36:32

笔记本ThinkPad T4

2009-09-03 15:22:05

RHEL5内存红帽

2023-08-28 07:51:24

8G内存Swap

2013-12-05 09:20:58

中移动4G牌照4G网络

2013-07-15 09:20:55

4G中国移动TD-LTE

2015-01-28 16:04:43

2013-12-17 09:52:55

4G移动互联网

2012-08-10 11:00:10

4GLTE

2014-08-18 09:35:13

4G

2020-09-21 15:59:23

4G5G网络
点赞
收藏

51CTO技术栈公众号