﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-这不是最好的时代,&amp;nbsp;也不是最坏的时代。-随笔分类-编程体会</title><link>http://www.cnitblog.com/benwhite/category/4048.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 10:50:55 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 10:50:55 GMT</pubDate><ttl>60</ttl><item><title>【转】VC 常用插件和界面库 </title><link>http://www.cnitblog.com/benwhite/archive/2008/03/28/41620.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Fri, 28 Mar 2008 07:18:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2008/03/28/41620.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/41620.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2008/03/28/41620.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/41620.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/41620.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">VC </span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">常用插件</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">  <br />1.Visual Assist</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">（强烈推荐）</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<a href="http://www.wholetomato.com/" target="_blank">http://www.wholetomato.com/</a>
						<br />VA</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">从</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">5.0</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">一直到现在的</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">VAX</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">，功能越来越强大，除了以前版本中的自动识别各种关键字，系统函数，成员变量，自动给出输入提示，自动更正大小写错误，自动标示错误等等以外，最新的版本中还在</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />WorkSpace</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">窗口中加入一个</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">VA View</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">，可以更方便的查找工程中的文件、类和变量。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />2.WndTabs</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">（强烈推荐）</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<a href="http://www.wndtabs.com/" target="_blank">http://www.wndtabs.com/</a>
						<br />WndTabs</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">主要是在编辑窗口中显示了所有已经打开的文件，在</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">VC</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">中能够更方便的操作这些文件，比如修改文件属性，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">copy</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">文件路径、文件名等，并且还开放源代码，你要是愿意的话，可以添加自己很兴趣的功能。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />3.LineCounter<br /><a href="http://www.wndtabs.com/" target="_blank">http://www.wndtabs.com/</a><br /><br /></span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">用来统计整个工程的代码行数，包括总行数、代码行数、注释行数、空行数等，并且对多个工程一起统计时，不会把相同的文件计算多次</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">.<br /><br />4.Spelly<br /><a href="http://www.wndtabs.com/" target="_blank">http://www.wndtabs.com/</a>  <br /></span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">一个拼写检查的插件，可以对整个文件或所选部分进行拼写检查，支持</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">C/C++/C#, VB, Fortran </span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">HTML</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />5.SourceStyler C++<br /><a href="http://www.sourcestyler.com/" target="_blank">http://www.sourcestyler.com/</a><br /></span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">此插件是针对</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">C++</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">的一个格式化工具，可以针对自己的编码习惯，选择一种编码风格，也可以自己定义，而且定义非常详细，有表达式、指针、模板、类、枚举等十几种，肯定能满足你的需要</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />6.Numega BoundsChecker</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">（强烈推荐）</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">是针对</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">Visual C++6.0</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">应用程序的最为全面的错误检测工具。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">BoundsChecker </span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">能自动指出静态，堆栈内存错误和资源泄漏问题。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">BoundsChecker </span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">能够校验最新的</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana"> Windows APIs</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">，包括</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana"> ActiveX, DirectX, OLE/COM, ODBC</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">等等。能够发现与</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana"> Windows </span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">平台兼容性。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />7.BCGControlBar Library <br /></span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">非常好的一套应用于</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">vc6</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">的界面扩展类库，轻松的作出</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana"> vc2003 </span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">的界面。并且给了各种界面例子，如</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">vc.net</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">outlook</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">、更换皮肤等等。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />8.Comment Wizard<br />Visual C++</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">插件，提供了</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">Visual C++</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">源代码注解标准化与自动化功能。在它的帮助下，您可快速创建标头文件信息注解，文件中模块注解，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana"> C++</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">处理方式，以及Ｃ语言功能与历史校正功能注解，等等。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />
						<br />VC </span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">界面库</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">收集</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
						<br />
						<br />GuiToolkit(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">开源，类似</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">Visual Studio 2003</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">风格</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://www.beyondata.com/default.htm" target="_blank">http://www.beyondata.com/default.htm</a><br /><br />GardenUI(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">免费，界面效果挺好的</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">,XML</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">，代码</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">界面</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">分离</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://www.gardenui.com/" target="_blank">http://www.gardenui.com/</a><br /><br />CJLib(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">开源，免费，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">UNICODE</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">编码</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">,</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">是</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">xtreme toolkit</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">的前生，但</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">xtreme toolkit</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">收费了</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://www.codejock.com/" target="_blank">http://www.codejock.com/</a><br /><br />LibUIDK(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">部分免费，不开源，效果好</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">,</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">适合贴图</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://www.iuishop.com/download.htm" target="_blank">http://www.iuishop.com/download.htm</a><br /><br />BCGControlBar(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">收费，界面感觉和</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">Office</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">类似</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://www.bcgsoft.com/" target="_blank">http://www.bcgsoft.com</a><br /><br />SKin++(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">收费，界面很好看</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://www.uipower.com/" target="_blank">http://www.uipower.com/</a><br /><br />SkinMagic(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">与</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">SKin++</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">类似</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://appspeed.com/html/download.html" target="_blank">http://appspeed.com/html/download.html</a><br /><br />ActiveSkin(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">未知</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">)<br /><a href="http://www.softshape.com/software/develop/" target="_blank">http://www.softshape.com/software/develop/</a><br /><br />SYGUI(</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">收费</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">,</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: 'Times New Roman'">类似</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">Office)<br /><a href="http://www.sygui.com/" target="_blank">http://www.sygui.com/</a><br /></span>
		</p>
<img src ="http://www.cnitblog.com/benwhite/aggbug/41620.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2008-03-28 15:18 <a href="http://www.cnitblog.com/benwhite/archive/2008/03/28/41620.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载] 对一些编程初学者的良言警句</title><link>http://www.cnitblog.com/benwhite/archive/2008/03/18/41090.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Tue, 18 Mar 2008 05:27:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2008/03/18/41090.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/41090.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2008/03/18/41090.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/41090.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/41090.html</trackback:ping><description><![CDATA[
<p>我始终认为，对一个初学者来说，IT界的技术风潮是不可以追赶的，而且也没有能力去追赶。我时常看 见自己的DDMM们把课本扔了，去卖些价格不菲的诸如C#, VB.Net 这样的大部头，这让我感到非常痛心。</p>
<p>而许多搞不清指针是咋回事的BBS站友眉飞色舞的讨论C#里面可以不用指针等等则让我觉得好笑。C++就象当年的ASP一样，"忽如一夜春风来，千树万树梨花开"，结果许多学校的信息学院成了"Web 学院"。</p>
<p>96,97级的不少大学生都去做Web了。当然我没有任何歧视某一行业的意识。我只是觉得如 果他们把追赶这些时髦技术的时间多花一点在基础的课程上应该是可以走得更远的。</p>
<p><strong>几个误区</strong></p>
<p>初学者对C++风潮的追赶其实也只是学习过程中经常遇到的几个误区之一。我将用一些实际的例子来说明这 些现象，你可以按部就班的看看自己是不是属于其中的一种或者几种：</p>
<p><strong>认为计算机技术等于编程技术</strong>：</p>
<p>有些人即使没有这个想法，在潜意识中也有这样的冲动。让我奇怪的是，许多信息学院的学生也有这样的念头。认为计算机专业就是编程专业，与编程无关的，或者不太相关的课程他统统都不管，极端的学生只要书上没带"编程"两个字他就不看。</p>
<p>其实编程只是计算机技术应用过程中一种复杂性最低的劳动，这就是为什么IT业最底层的人是程序员( CODER)。计算机技术包括了多媒体，计算机网络，人工智能，模式识别，管理信息系统等等这些方面。</p>
<p>编程工作只是在这些具体技术在理论研究或者工程实践的过程中表达算法的过程。编程的人不一定对计算机技术的了解就一定很高。而一个有趣的现象是，不少大师级的计算机技术研究者是不懂编程的。网上的炒作和现实中良好的工作待遇把编程这种劳动神秘化了。其实每一个程序员心里都明白，自己这些东西，学的时候并不比其它专业难，所以自然也不会高档到哪里去。</p>
<p><strong>咬文嚼字的孔乙己作风</strong>：</p>
<p>我见过一本女生的《计算机网络原理》教材，这个女生象小学生一样在书上划满了横杠杠，笔记做得满满的，打印出来一定比教材还厚。我不明白的是，象计算机网络原理这样的课程有必要做笔记？我们的应试教育的确害了不少学生，在上《原理》这一类课程的时候许多学生象学《马列原理》一样逐字背诵记忆。</p>
<p>这乃是我见过的最愚蠢的行为。所谓《原理》，即是需要掌握它为什么这样做，学习why，而不是how(怎样做)。极端认真的学生背下以太网的网线最大长度，数据帧的长度，每个字段的意义，IP报头的格式等等，但是忘了路由的原则，忘了TCP/IP协议设计的宗旨。总之许多人花了大量的时间把书背得滚瓜烂熟却等于什么也没学。</p>
<p>在学习编程的时候这些学生也是这样，他们确切的记得C++语法的各个细节。看完了C++教程后看《Thinking in C++》(确实是好书)，《Inside C++》，《C++ reference》，this C++,thatC++……，然后是网上各种各样的关于C++语法的奇闻逸事，然后发现自己又忘了C++的一些语法，最后回头继续恶补…。有个师弟就跟我说："C++ 太难了，学了这里忘了那里，学了继承忘了模板。"我的回答道："你不去学就容易了"。我并没有教坏他，只是告诉他，死抠C++的语法就和孔已己炫耀茴香豆的茴字有几种写法一样毫无意义。你根本不需要对的C++语法太关心，动手编程就是了，有不记得的地方一查MSDN就立马搞定。我有个结论就是，实际的开发过程中对程序语法的了解是最微不足道的知识。这是为什么我在为同学用Basic(我以前从没有学过它)写一个小程序的时候，只花了半个小时看了看语法，然后再用半个小时完成了程序，而一个小时后我又完全忘记了Basic 的所有关键字。</p>
<p><strong>不顾基础，盲目追赶时髦技术</strong>：</p>
<p>终于点到题目上来了。大多数的人都希望自己的东西能够马上跑起来，变成钱。这种想法对一个已经进入职业领域的程序员或者项目经理来说是合理的，而且IT技术进步是如此的快，不跟进就是失业。但是对于初学者来说(尤其是时间充裕的大中专在校生)，这种想法是另人费解的。一个并未进入到行业竞争中来的初学者最大的资本便是他有足够的时间沉下心来学习基础性的东西，学习why 而不是how。时髦的技术往往容易掌握，而且越来越容易掌握，这是商业利益的驱使，为了最大化的降低软件开发的成本。但在IT领域内的现实就是这样，越容易掌握的东西，学习的人越多，而且淘汰得越快。每一次新的技术出来，都有许多初学者跟进，这些初学者由于缺乏必要的基础而使得自己在跟进的过程中花费大量的时间，而等他学会了，这种技术也快淘汰了。基础的课程，比方数据结构，操作系统原理等等虽然不能让你立马就实现一个linux(这是许多人嘲笑理论课程无用的原因)，但它们能够显著的减少你在学习新技术时学习曲线的坡度。而且对于许多关键的技术(比方Win32 SDK 程序的设计，DDK的编程)来说甚至是不可或缺的。</p>
<p>一个活生生的例子是我和我的一个同学，在大一时我还找不到开机按纽，他已经会写些简单的汇编程序了。我把大二的所有时间花在了汇编，计算机体系结构，数据结构，操作系统原理等等这些课程的学习上，而他则开始学习HTML和VB，并追赶ASP的潮流。大三的时候我开始学习Windows 操作系统原理，学习SDK编程，时间是漫长的，这时我才能够用VC开发出象模象样的应用程序。我曾一度因为同学的程序已经能够运行而自己还在学习如何创建对话框而懊恼不已，但临到毕业才发现自己的选择是何等的正确。和我谈判的公司开出的薪水是他的两倍还多。下面有一个不很恰当的比方：假设学习VB编程需要4个月，学习基础课程和VC的程序设计需要1年。那么如果你先学VB，再来学习后者，时间不会减少，还是1年，而反过来，如果先学习后者，再来学VB，也许你只需要1个星期就能学得非常熟练。</p>
<p><strong>几个重要的基础课程</strong></p>
<p>如果你是学生，或者如果你有充足的时间。我建议你仔细的掌握下面的知识。我的建议是针对那些希望在IT技术上有所成就的初学者。同时我还列出了一些书目，这些书应该都还可以在书店买到。说实在的，我在读其他人的文章时最大的心愿就是希望作者列出一个书单。</p>
<p>大学英语-不要觉得好笑。我极力推荐这门课程是因为没有专业文档的阅读能力是不可想象的。中文的翻译往往在猴年马月才会出来，而现在的许多出版社干脆就直接把E文印刷上去。学习的方法是强迫自己看原版的教材，开始会看不懂，用多了自然熟练。吃得苦下得狠心绝对是任何行业都需要的品质。</p>
<p>计算机体系结构和汇编语言-关于体系结构的书遍地都是，而且也大同小异，倒是汇编有一本非常好的书。《80x86汇编语言程序设计教程》(清华大学出版社，黑色封面，杨季文著)。你需要着重学习386后保护模式的程序设计。否则你在学习现代操作系统底层的一些东西的时候会觉得是在看天书。</p>
<p>计算机操作系统原理-我们的开发总是在特定的操作系统上进行，如果不是，只有一种可能：你在自己实现一个操作系统。无论如何，操作系统原理是必读的。这就象我们为一个芯片制作外围设备时，芯片基本的工作时序是必需了解的。这一类书也很多，我没有发现哪一本书非常出众。只是觉得在看完了这些书后如果有空就应该看看《Inside Windows 2000》(微软出版社，我看的是E文版的，中文的书名想必是Windows 2000 技术内幕之类吧)。关于学习它的必要性，ZDNET上的另一篇文章已经有过论述。</p>
<p>数据结构和算法-这门课程能够决定一个人程序设计水平的高低，是一门核心课程。我首选的是清华版的(朱战立，刘天时)。很多人喜欢买C++版的，但我觉得没有必要。C++的语法让算法实现过程变得复杂多了，而且许多老师喜欢用模块这一东西让算法变得更复杂。倒是在学完了C版的书以后再来浏览一下C++的版的书是最好的。</p>
<p>软件工程-这门课程是越到后来就越发现它的重要，虽然刚开始看时就象看马哲一样不知所云。我的建议是看《实用软件工程》(黄色，清华)。不要花太多的时间去记条条框框，看不懂就跳过去。在每次自己完成了一个软件设计任务(不管是练习还是工作)以后再来回顾回顾，每次都会有收获。</p>
<p>Windows 程序设计-《北京大学出版社，Petzold著》我建议任何企图设计Windows 程序的人在学习VC以前仔细的学完它。而且前面的那本《Inside Windows 2000》也最好放到这本书的后面读。</p>
<p>在这本书中，没有C++，没有GUI，没有控件。有的就是如何用原始的C语言来完成Windows 程序设计。在 学完了它以后，你才会发现VC其实是很容易学的。千万不要在没有看完这本书以前提前学习VC，你最好碰都不要碰。我知道的许多名校甚至都已经用它作为教材进行授课。可见其重要。</p>
<p>上面的几门课程我认为是必学的重要课程(如果你想做Windows 程序员)。</p>
<p>对于其它的课程有这样简单的选择方法：如果你是计算机系的，请学好你所有的专业基础课。如果不是，请参照计算机系的课程表。如果你发现自己看一本书时无法看下去了，请翻到书的最后，看看它的参考文献，找到它们并学习它们，再回头看这本书。如果一本书的书名中带有"原理"两个字，你一定不要去记忆它其中的细节，你应该以一天至少50页的速度掌握其要领。尽可能多的在计算机上实践一种理论或者算法。</p>
<p>你还可以在CSDN上阅读到许多书评。这些书评能够帮助你决定读什么样的书。</p>
<p><strong>日三省乎己</strong></p>
<p>每天读的书太多，容易让人迷失方向。一定要在每天晚上想想自己学了些什么，还有些什么相关的东西需要掌握，自己对什么最感兴趣，在一本书上花的时间太长还是不够等等。同时也应该多想想未来最有可能出现的应用，这样能够让你不是追赶技术潮流而是引领技术潮流。同时，努力使用现在已经掌握的技术和理论去制作具有一定新意的东西。坚持这样做能够让你真正成为一个软件"研发者"而不仅仅是一个CODER。</p>
<p><strong>把最多的时间花在学习上</strong></p>
<p>这是对初学者最后的忠告。把每个星期玩SC或者CS的时间压缩到最少，不玩它们是最好的。同时，如果你的ASP技术已经能够来钱，甚至有公司请你兼职的话，这就证明你的天份能够保证你在努力的学习之后取得更好的收益，你应该去做更复杂的东西。眼光放长远一些，这无论是对谁都是适用的。</p>
<p>相信你已经能够决定是否学习C＃或者什么时候去学它了</p>
<p><span style="FONT-SIZE: 12px">本文链接：<a href="http://www.blueidea.com/tech/program/2008/5505.asp" target="_blank">http://www.blueidea.com/tech/program/2008/5505.asp</a></span></p>
<img src ="http://www.cnitblog.com/benwhite/aggbug/41090.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2008-03-18 13:27 <a href="http://www.cnitblog.com/benwhite/archive/2008/03/18/41090.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>变量定义与声明的区别</title><link>http://www.cnitblog.com/benwhite/archive/2007/12/11/37562.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Mon, 10 Dec 2007 16:56:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2007/12/11/37562.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/37562.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2007/12/11/37562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/37562.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/37562.html</trackback:ping><description><![CDATA[终于明白了 札记如下<br />声明：告诉编译器变量的类型 在哪里 或者函数的特征（返回值 参数类型 个数）<br />定义：告诉编译器 在此处分配存储空间 建立变量和函数<br /><br />同一变量定义只有一个（干嘛要多处分配空间呢 内存很宝贵的～）<br />但是可以声明多次<br /><br />变量有点混淆－－<br />int a； 是个声明 也是个定义<br />extern int a； 只是声明<br />所以声明包含定义，有足够的信息让编译器建立变量的声明 就是一个定义<br />为了让int a；不是定义（别给a分配空间） 前面加extern吧<br />（所以 extern int a＝1；是要出错的 －－BB）<br /><br />函数很清楚－－<br />声明就是没有函数体的 定义则有<br />事实上函数声明前本来也要加extern的 但是可以省略 因为大家都很懒 谁想多打字呢？<br /><br />end～<br /><br />附送 程序内存简介<br /><p class="MsoNormal" style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: left" align="left"><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体"><font size="3">一个由c/C++编译的程序占用的内存分为以下几个部分 </font></span></p><p class="MsoNormal" style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: left" align="left"><font size="3"><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">1、栈区（stack）</span><span style="FONT-SIZE: 10pt"><font face="Times New Roman">—</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体"> 由编译器自动分配释放，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。 </span></font></p><p class="MsoNormal" style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: left" align="left"><font size="3"><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">2、堆区（heap） </span><span style="FONT-SIZE: 10pt"><font face="Times New Roman">—</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体"> 一般由程序员分配释放，若程序员不释放，程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表，呵呵。 </span></font></p><p class="MsoNormal" style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: left" align="left"><font size="3"><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">3、全局区（静态区）（static）</span><span style="FONT-SIZE: 10pt"><font face="Times New Roman">—</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域，未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 </span></font></p><p class="MsoNormal" style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: left" align="left"><font size="3"><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">4、文字常量区 </span><span style="FONT-SIZE: 10pt"><font face="Times New Roman">—</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">常量字符串就是放在这里的。 程序结束后由系统释放 </span></font></p><p class="MsoNormal" style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: left" align="left"><font size="3"><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">5、程序代码区</span><span style="FONT-SIZE: 10pt"><font face="Times New Roman">—</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">存放函数体的二进制代码。</span></font></p><img src ="http://www.cnitblog.com/benwhite/aggbug/37562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2007-12-11 00:56 <a href="http://www.cnitblog.com/benwhite/archive/2007/12/11/37562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言程序设计（K&amp;R）笔记</title><link>http://www.cnitblog.com/benwhite/archive/2007/12/07/37464.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Fri, 07 Dec 2007 08:34:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2007/12/07/37464.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/37464.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2007/12/07/37464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/37464.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/37464.html</trackback:ping><description><![CDATA[
		<p>"重读K&amp;R的书，感慨许久。其语言流畅，组织合理，既介绍了语言，也旁通了算法，结构，库函数，系统调用，受益无穷。当年由于初读英文原版，生词太多而放弃，现在回想，有些感慨。不管怎样，现在读来，一气呵成，perfect～！"                          －－题记<br /><br />C1：A Tutorial Introduction<br />1.1 hello world 函数<br />1.2 变量 表达式 温度转换函数<br />1.3 for <br />1.4 define<br />1.5 字符输入输出 单词计数<br />1.6 数组<br />1.7 函数<br />1.8 参数 按值传递<br />1.9 字符数组<br />1.10 外部变量<br /><br />C2：类型 操作符 表达式<br />2.1 变量名 约定<br />2.2 类型 不同的大小<br />2.3 常量<br />      字符常量是整数 区分'x' "x" <br />      枚举<br />2.4 声明<br />2.5 算术操作符 +-*/%<br />2.6 关系操作符 &gt; &gt;= &lt; &lt;= == != || &amp;&amp;<br />2.7 类型转换 <br />      规则：窄－－》宽  低－－》高<br />      情形：赋值 函数参数传递 强制<br />2.8 ++ --  <br />2.9 位操作 &gt;&gt; &lt;&lt; ~ <br />2.10  赋值操作符 +＝ －＝<br />2.11 条件表达式 ？：<br />2.12 优先级<br />        注意side effect （由于操作数计算顺序不同 导致）<br /><br />C3：Control Flow<br />选择 循环 break continue goto<br /><br />C4：函数 程序结构<br />4.1 基础<br />4.2 返回非int 的函数 atof()<br />      注意 声明和定义 返回类型不匹配的情况<br />       参数为空 一定要写 viod<br />4.3 外部变量<br />        函数内部不能定义函数<br />         计算器程度<br />4.4 范围 scope<br />      外部变量：从定义处 到文件尾<br />4.5 头文件<br />4.6 static 变量<br />      为了隐藏 变量 为本文件可见<br />      或者 函数的累积参数之用<br />4.7 register 变量<br />4.8 结构<br />      内部变量为隐藏掉外部同名的变量 小心<br />4.9 初始化<br />      外部变量和static 只初始化一次 所以必须是常量赋值<br />4.10 递归 快速排序<br />4.11 预处理<br />        #if #ifndef ## #<br /><br />C5: 指针 数组<br />5.1 指针和地址<br />      &amp;只取内存内的对象地址。不能是表达式 常量 register<br />5.2 指针作为函数参数<br />5.3 指针vs 数组<br />      pa＝a<br />5.4 地址算术<br />      alloc afree<br />     规则：同类型指针才能赋值 加减整数 同一数组的指针才能比较 与0比较或赋值<br />5.5 字符指针<br />     strcmp strcpy<br />5.6 指针数组 指针的指针<br />5.7 多维数组<br />5.8 初始化指针数组<br />5.9 指针vs多维数组<br />5.10 命令行参数<br />    argc argv<br />5.11 函数指针<br />     int (* cmp) (void *,void *)<br />5.12 复杂声明<br />一个解析程序<br /><br />C6 结构体 structure<br />6.1 基础 point<br />6.2 解构体 函数<br />6.3 结构体数组<br />      关键字统计程序<br />6.4 结构体指针<br />6.5 自引用结构<br />  二叉树<br />6.6 表查找<br />      看看＃define是 怎么实现的<br />      哈希表<br />6.7 typedef<br />       跨平台 便于阅读和编写<br />6.8 Union<br />6.9 位域<br /><br />C7： input output<br />介绍 printf的实现 文件的读写<br /><br />C8： Unix 系统调用<br />读写的实现 文件描述符 目录的操作 以及malloc的实现<br /><br />附录A 使用手册<br />B 库函数介绍<br />C 标准的修改汇总</p>
<img src ="http://www.cnitblog.com/benwhite/aggbug/37464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2007-12-07 16:34 <a href="http://www.cnitblog.com/benwhite/archive/2007/12/07/37464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《堆和栈的区别（转贴）》</title><link>http://www.cnitblog.com/benwhite/archive/2007/04/04/25160.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Wed, 04 Apr 2007 08:43:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2007/04/04/25160.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/25160.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2007/04/04/25160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/25160.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/25160.html</trackback:ping><description><![CDATA[<p style="FONT-FAMILY: Arial">非本人作也!因非常经典,所以收归旗下,与众人阅之!原作者不祥!</p>
<div class=postbody style="FONT-FAMILY: Arial">堆和栈的区别<br>一、预备知识—程序的内存分配<br>一个由c/C++编译的程序占用的内存分为以下几个部分<br>1、栈区（stack）—&nbsp;由编译器自动分配释放&nbsp;，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。<br>2、堆区（heap）&nbsp;—&nbsp;一般由程序员分配释放，&nbsp;若程序员不释放，程序结束时可能由OS回收&nbsp;。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表，呵呵。<br>3、全局区（静态区）（static）—，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域，&nbsp;未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。&nbsp;-&nbsp;程序结束后有系统释放&nbsp;<br>4、文字常量区—常量字符串就是放在这里的。&nbsp;程序结束后由系统释放<br>5、程序代码区—存放函数体的二进制代码。<br>二、例子程序&nbsp;<br>这是一个前辈写的，非常详细&nbsp;<br>//main.cpp&nbsp;<br>int&nbsp;a&nbsp;=&nbsp;0;&nbsp;全局初始化区&nbsp;<br>char&nbsp;*p1;&nbsp;全局未初始化区&nbsp;<br>main()&nbsp;<br>{&nbsp;<br>int&nbsp;b;&nbsp;栈&nbsp;<br>char&nbsp;s[]&nbsp;=&nbsp;"abc";&nbsp;栈&nbsp;<br>char&nbsp;*p2;&nbsp;栈&nbsp;<br>char&nbsp;*p3&nbsp;=&nbsp;"123456";&nbsp;123456\0在常量区，p3在栈上。&nbsp;<br>static&nbsp;int&nbsp;c&nbsp;=0；&nbsp;全局（静态）初始化区&nbsp;<br>p1&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br>p2&nbsp;=&nbsp;(char&nbsp;*)malloc(20);&nbsp;<br>分配得来得10和20字节的区域就在堆区。&nbsp;<br>strcpy(p1,&nbsp;"123456");&nbsp;123456\0放在常量区，编译器可能会将它与p3所指向的"123456"优化成一个地方。&nbsp;<br>}&nbsp;
<p style="FONT-FAMILY: Arial"></p>
<p style="FONT-FAMILY: Arial"><br>二、堆和栈的理论知识&nbsp;<br>2.1申请方式&nbsp;<br>stack:&nbsp;<br>由系统自动分配。&nbsp;例如，声明在函数中一个局部变量&nbsp;int&nbsp;b;&nbsp;系统自动在栈中为b开辟空间&nbsp;<br>heap:&nbsp;<br>需要程序员自己申请，并指明大小，在c中malloc函数&nbsp;<br>如p1&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br>在C++中用new运算符&nbsp;<br>如p2&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br>但是注意p1、p2本身是在栈中的。&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>2.2&nbsp;<br>申请后系统的响应&nbsp;<br>栈：只要栈的剩余空间大于所申请空间，系统将为程序提供内存，否则将报异常提示栈溢出。&nbsp;<br>堆：首先应该知道操作系统有一个记录空闲内存地址的链表，当系统收到程序的申请时，&nbsp;<br>会遍历该链表，寻找第一个空间大于所申请空间的堆结点，然后将该结点从空闲结点链表中删除，并将该结点的空间分配给程序，另外，对于大多数系统，会在这块内存空间中的首地址处记录本次分配的大小，这样，代码中的delete语句才能正确的释放本内存空间。另外，由于找到的堆结点的大小不一定正好等于申请的大小，系统会自动的将多余的那部分重新放入空闲链表中。&nbsp;</p>
<p style="FONT-FAMILY: Arial">2.3申请大小的限制&nbsp;<br>栈：在Windows下,栈是向低地址扩展的数据结构，是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的，在WINDOWS下，栈的大小是2M（也有的说是1M，总之是一个编译时就确定的常数），如果申请的空间超过栈的剩余空间时，将提示overflow。因此，能从栈获得的空间较小。&nbsp;<br>堆：堆是向高地址扩展的数据结构，是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的，自然是不连续的，而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见，堆获得的空间比较灵活，也比较大。&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>2.4申请效率的比较：&nbsp;<br>栈由系统自动分配，速度较快。但程序员是无法控制的。&nbsp;<br>堆是由new分配的内存，一般速度比较慢，而且容易产生内存碎片,不过用起来最方便.&nbsp;<br>另外，在WINDOWS下，最好的方式是用VirtualAlloc分配内存，他不是在堆，也不是在栈是直接在进程的地址空间中保留一快内存，虽然用起来最不方便。但是速度快，也最灵活。&nbsp;</p>
<p style="FONT-FAMILY: Arial">2.5堆和栈中的存储内容&nbsp;<br>栈：&nbsp;在函数调用时，第一个进栈的是主函数中后的下一条指令（函数调用语句的下一条可执行语句）的地址，然后是函数的各个参数，在大多数的C编译器中，参数是由右往左入栈的，然后是函数中的局部变量。注意静态变量是不入栈的。&nbsp;<br>当本次函数调用结束后，局部变量先出栈，然后是参数，最后栈顶指针指向最开始存的地址，也就是主函数中的下一条指令，程序由该点继续运行。&nbsp;<br>堆：一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。&nbsp;</p>
<p style="FONT-FAMILY: Arial">2.6存取效率的比较&nbsp;</p>
<p style="FONT-FAMILY: Arial">char&nbsp;s1[]&nbsp;=&nbsp;"aaaaaaaaaaaaaaa";&nbsp;<br>char&nbsp;*s2&nbsp;=&nbsp;"bbbbbbbbbbbbbbbbb";&nbsp;<br>aaaaaaaaaaa是在运行时刻赋值的；&nbsp;<br>而bbbbbbbbbbb是在编译时就确定的；&nbsp;<br>但是，在以后的存取中，在栈上的数组比指针所指向的字符串(例如堆)快。&nbsp;<br>比如：&nbsp;<br>#include&nbsp;<br>void&nbsp;main()&nbsp;<br>{&nbsp;<br>char&nbsp;a&nbsp;=&nbsp;1;&nbsp;<br>char&nbsp;c[]&nbsp;=&nbsp;"1234567890";&nbsp;<br>char&nbsp;*p&nbsp;="1234567890";&nbsp;<br>a&nbsp;=&nbsp;c[1];&nbsp;<br>a&nbsp;=&nbsp;p[1];&nbsp;<br>return;&nbsp;<br>}&nbsp;<br>对应的汇编代码&nbsp;<br>10:&nbsp;a&nbsp;=&nbsp;c[1];&nbsp;<br>00401067&nbsp;8A&nbsp;4D&nbsp;F1&nbsp;mov&nbsp;cl,byte&nbsp;ptr&nbsp;[ebp-0Fh]&nbsp;<br>0040106A&nbsp;88&nbsp;4D&nbsp;FC&nbsp;mov&nbsp;byte&nbsp;ptr&nbsp;[ebp-4],cl&nbsp;<br>11:&nbsp;a&nbsp;=&nbsp;p[1];&nbsp;<br>0040106D&nbsp;8B&nbsp;55&nbsp;EC&nbsp;mov&nbsp;edx,dword&nbsp;ptr&nbsp;[ebp-14h]&nbsp;<br>00401070&nbsp;8A&nbsp;42&nbsp;01&nbsp;mov&nbsp;al,byte&nbsp;ptr&nbsp;[edx+1]&nbsp;<br>00401073&nbsp;88&nbsp;45&nbsp;FC&nbsp;mov&nbsp;byte&nbsp;ptr&nbsp;[ebp-4],al&nbsp;<br>第一种在读取时直接就把字符串中的元素读到寄存器cl中，而第二种则要先把指针值读到edx中，在根据edx读取字符，显然慢了。&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>2.7小结：&nbsp;<br>堆和栈的区别可以用如下的比喻来看出：&nbsp;<br>使用栈就象我们去饭馆里吃饭，只管点菜（发出申请）、付钱、和吃（使用），吃饱了就走，不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作，他的好处是快捷，但是自由度小。&nbsp;<br>使用堆就象是自己动手做喜欢吃的菜肴，比较麻烦，但是比较符合自己的口味，而且自由度大。&nbsp;</p>
<p style="FONT-FAMILY: Arial">windows进程中的内存结构<br><br>在阅读本文之前，如果你连堆栈是什么多不知道的话，请先阅读文章后面的基础知识。&nbsp;</p>
<p style="FONT-FAMILY: Arial">接触过编程的人都知道，高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢？程序又是如何使用这些变量的呢？下面就会对此进行深入的讨论。下文中的C语言代码如没有特别声明，默认都使用VC编译的release版。&nbsp;</p>
<p style="FONT-FAMILY: Arial">首先，来了解一下&nbsp;C&nbsp;语言的变量是如何在内存分部的。C&nbsp;语言有全局变量(Global)、本地变量(Local)，静态变量(Static)、寄存器变量(Regeister)。每种变量都有不同的分配方式。先来看下面这段代码：&nbsp;</p>
<p style="FONT-FAMILY: Arial">#include&nbsp;&lt;stdio.h&gt;&nbsp;</p>
<p style="FONT-FAMILY: Arial">int&nbsp;g1=0,&nbsp;g2=0,&nbsp;g3=0;&nbsp;</p>
<p style="FONT-FAMILY: Arial">int&nbsp;main()&nbsp;<br>{&nbsp;<br>static&nbsp;int&nbsp;s1=0,&nbsp;s2=0,&nbsp;s3=0;&nbsp;<br>int&nbsp;v1=0,&nbsp;v2=0,&nbsp;v3=0;&nbsp;</p>
<p style="FONT-FAMILY: Arial">//打印出各个变量的内存地址&nbsp;</p>
<p style="FONT-FAMILY: Arial">printf("0x%08x\n",&amp;v1);&nbsp;//打印各本地变量的内存地址&nbsp;<br>printf("0x%08x\n",&amp;v2);&nbsp;<br>printf("0x%08x\n\n",&amp;v3);&nbsp;<br>printf("0x%08x\n",&amp;g1);&nbsp;//打印各全局变量的内存地址&nbsp;<br>printf("0x%08x\n",&amp;g2);&nbsp;<br>printf("0x%08x\n\n",&amp;g3);&nbsp;<br>printf("0x%08x\n",&amp;s1);&nbsp;//打印各静态变量的内存地址&nbsp;<br>printf("0x%08x\n",&amp;s2);&nbsp;<br>printf("0x%08x\n\n",&amp;s3);&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">编译后的执行结果是：&nbsp;</p>
<p style="FONT-FAMILY: Arial">0x0012ff78&nbsp;<br>0x0012ff7c&nbsp;<br>0x0012ff80&nbsp;</p>
<p style="FONT-FAMILY: Arial">0x004068d0&nbsp;<br>0x004068d4&nbsp;<br>0x004068d8&nbsp;</p>
<p style="FONT-FAMILY: Arial">0x004068dc&nbsp;<br>0x004068e0&nbsp;<br>0x004068e4&nbsp;</p>
<p style="FONT-FAMILY: Arial">输出的结果就是变量的内存地址。其中v1,v2,v3是本地变量，g1,g2,g3是全局变量，s1,s2,s3是静态变量。你可以看到这些变量在内存是连续分布的，但是本地变量和全局变量分配的内存地址差了十万八千里，而全局变量和静态变量分配的内存是连续的。这是因为本地变量和全局/静态变量是分配在不同类型的内存区域中的结果。对于一个进程的内存空间而言，可以在逻辑上分成3个部份：代码区，静态数据区和动态数据区。动态数据区一般就是&#8220;堆栈&#8221;。&#8220;栈(stack)&#8221;和&#8220;堆(heap)&#8221;是两种不同的动态数据区，栈是一种线性结构，堆是一种链式结构。进程的每个线程都有私有的&#8220;栈&#8221;，所以每个线程虽然代码一样，但本地变量的数据都是互不干扰。一个堆栈可以通过&#8220;基地址&#8221;和&#8220;栈顶&#8221;地址来描述。全局变量和静态变量分配在静态数据区，本地变量分配在动态数据区，即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>├———————┤低端内存区域&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;动态数据区&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;代码区&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;静态数据区&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤高端内存区域&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>堆栈是一个先进后出的数据结构，栈顶地址总是小于等于栈的基地址。我们可以先了解一下函数调用的过程，以便对堆栈在程序中的作用有更深入的了解。不同的语言有不同的函数调用规定，这些因素有参数的压入规则和堆栈的平衡。windows&nbsp;API的调用规则和ANSI&nbsp;C的函数调用规则是不一样的，前者由被调函数调整堆栈，后者由调用者调整堆栈。两者通过&#8220;__stdcall&#8221;和&#8220;__cdecl&#8221;前缀区分。先看下面这段代码：&nbsp;</p>
<p style="FONT-FAMILY: Arial">#include&nbsp;&lt;stdio.h&gt;&nbsp;</p>
<p style="FONT-FAMILY: Arial">void&nbsp;__stdcall&nbsp;func(int&nbsp;param1,int&nbsp;param2,int&nbsp;param3)&nbsp;<br>{&nbsp;<br>int&nbsp;var1=param1;&nbsp;<br>int&nbsp;var2=param2;&nbsp;<br>int&nbsp;var3=param3;&nbsp;<br>printf("0x%08x\n",&#182;m1);&nbsp;//打印出各个变量的内存地址&nbsp;<br>printf("0x%08x\n",&#182;m2);&nbsp;<br>printf("0x%08x\n\n",&#182;m3);&nbsp;<br>printf("0x%08x\n",&amp;var1);&nbsp;<br>printf("0x%08x\n",&amp;var2);&nbsp;<br>printf("0x%08x\n\n",&amp;var3);&nbsp;<br>return;&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">int&nbsp;main()&nbsp;<br>{&nbsp;<br>func(1,2,3);&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">编译后的执行结果是：&nbsp;</p>
<p style="FONT-FAMILY: Arial">0x0012ff78&nbsp;<br>0x0012ff7c&nbsp;<br>0x0012ff80&nbsp;</p>
<p style="FONT-FAMILY: Arial">0x0012ff68&nbsp;<br>0x0012ff6c&nbsp;<br>0x0012ff70&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>├———————┤&lt;—函数执行时的栈顶（ESP）、低端内存区域&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;var&nbsp;1&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;var&nbsp;2&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;var&nbsp;3&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;RET&nbsp;│&nbsp;<br>├———————┤&lt;—&#8220;__cdecl&#8221;函数返回后的栈顶（ESP）&nbsp;<br>│&nbsp;parameter&nbsp;1&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;parameter&nbsp;2&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;parameter&nbsp;3&nbsp;│&nbsp;<br>├———————┤&lt;—&#8220;__stdcall&#8221;函数返回后的栈顶（ESP）&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&lt;—栈底（基地址&nbsp;EBP）、高端内存区域&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>上图就是函数调用过程中堆栈的样子了。首先，三个参数以从又到左的次序压入堆栈，先压&#8220;param3&#8221;，再压&#8220;param2&#8221;，最后压入&#8220;param1&#8221;；然后压入函数的返回地址(RET)，接着跳转到函数地址接着执行（这里要补充一点，介绍UNIX下的缓冲溢出原理的文章中都提到在压入RET后，继续压入当前EBP，然后用当前ESP代替EBP。然而，有一篇介绍windows下函数调用的文章中说，在windows下的函数调用也有这一步骤，但根据我的实际调试，并未发现这一步，这还可以从param3和var1之间只有4字节的间隙这点看出来）；第三步，将栈顶(ESP)减去一个数，为本地变量分配内存空间，上例中是减去12字节(ESP=ESP-3*4，每个int变量占用4个字节)；接着就初始化本地变量的内存空间。由于&#8220;__stdcall&#8221;调用由被调函数调整堆栈，所以在函数返回前要恢复堆栈，先回收本地变量占用的内存(ESP=ESP+3*4)，然后取出返回地址，填入EIP寄存器，回收先前压入参数占用的内存(ESP=ESP+3*4)，继续执行调用者的代码。参见下列汇编代码：&nbsp;</p>
<p style="FONT-FAMILY: Arial">;--------------func&nbsp;函数的汇编代码-------------------&nbsp;</p>
<p style="FONT-FAMILY: Arial">:00401000&nbsp;83EC0C&nbsp;sub&nbsp;esp,&nbsp;0000000C&nbsp;//创建本地变量的内存空间&nbsp;<br>:00401003&nbsp;8B442410&nbsp;mov&nbsp;eax,&nbsp;dword&nbsp;ptr&nbsp;[esp+10]&nbsp;<br>:00401007&nbsp;8B4C2414&nbsp;mov&nbsp;ecx,&nbsp;dword&nbsp;ptr&nbsp;[esp+14]&nbsp;<br>:0040100B&nbsp;8B542418&nbsp;mov&nbsp;edx,&nbsp;dword&nbsp;ptr&nbsp;[esp+18]&nbsp;<br>:0040100F&nbsp;89442400&nbsp;mov&nbsp;dword&nbsp;ptr&nbsp;[esp],&nbsp;eax&nbsp;<br>:00401013&nbsp;8D442410&nbsp;lea&nbsp;eax,&nbsp;dword&nbsp;ptr&nbsp;[esp+10]&nbsp;<br>:00401017&nbsp;894C2404&nbsp;mov&nbsp;dword&nbsp;ptr&nbsp;[esp+04],&nbsp;ecx&nbsp;</p>
<p style="FONT-FAMILY: Arial">&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;（省略若干代码）&nbsp;</p>
<p style="FONT-FAMILY: Arial">:00401075&nbsp;83C43C&nbsp;add&nbsp;esp,&nbsp;0000003C&nbsp;;恢复堆栈，回收本地变量的内存空间&nbsp;<br>:00401078&nbsp;C3&nbsp;ret&nbsp;000C&nbsp;;函数返回，恢复参数占用的内存空间&nbsp;<br>;如果是&#8220;__cdecl&#8221;的话，这里是&#8220;ret&#8221;，堆栈将由调用者恢复&nbsp;</p>
<p style="FONT-FAMILY: Arial">;-------------------函数结束-------------------------&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>;--------------主程序调用func函数的代码--------------&nbsp;</p>
<p style="FONT-FAMILY: Arial">:00401080&nbsp;6A03&nbsp;push&nbsp;00000003&nbsp;//压入参数param3&nbsp;<br>:00401082&nbsp;6A02&nbsp;push&nbsp;00000002&nbsp;//压入参数param2&nbsp;<br>:00401084&nbsp;6A01&nbsp;push&nbsp;00000001&nbsp;//压入参数param1&nbsp;<br>:00401086&nbsp;E875FFFFFF&nbsp;call&nbsp;00401000&nbsp;//调用func函数&nbsp;<br>;如果是&#8220;__cdecl&#8221;的话，将在这里恢复堆栈，&#8220;add&nbsp;esp,&nbsp;0000000C&#8221;&nbsp;</p>
<p style="FONT-FAMILY: Arial">聪明的读者看到这里，差不多就明白缓冲溢出的原理了。先来看下面的代码：&nbsp;</p>
<p style="FONT-FAMILY: Arial">#include&nbsp;&lt;stdio.h&gt;&nbsp;<br>#include&nbsp;&lt;string.h&gt;&nbsp;</p>
<p style="FONT-FAMILY: Arial">void&nbsp;__stdcall&nbsp;func()&nbsp;<br>{&nbsp;<br>char&nbsp;lpBuff[8]="\0";&nbsp;<br>strcat(lpBuff,"AAAAAAAAAAA");&nbsp;<br>return;&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">int&nbsp;main()&nbsp;<br>{&nbsp;<br>func();&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">编译后执行一下回怎么样？哈，&#8220;"0x00414141"指令引用的"0x00000000"内存。该内存不能为"read"。&#8221;，&#8220;非法操作&#8221;喽！"41"就是"A"的16进制的ASCII码了，那明显就是strcat这句出的问题了。"lpBuff"的大小只有8字节，算进结尾的\0，那strcat最多只能写入7个"A"，但程序实际写入了11个"A"外加1个\0。再来看看上面那幅图，多出来的4个字节正好覆盖了RET的所在的内存空间，导致函数返回到一个错误的内存地址，执行了错误的指令。如果能精心构造这个字符串，使它分成三部分，前一部份仅仅是填充的无意义数据以达到溢出的目的，接着是一个覆盖RET的数据，紧接着是一段shellcode，那只要着个RET地址能指向这段shellcode的第一个指令，那函数返回时就能执行shellcode了。但是软件的不同版本和不同的运行环境都可能影响这段shellcode在内存中的位置，那么要构造这个RET是十分困难的。一般都在RET和shellcode之间填充大量的NOP指令，使得exploit有更强的通用性。&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>├———————┤&lt;—低端内存区域&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&lt;—由exploit填入数据的开始&nbsp;<br>│&nbsp;│&nbsp;<br>│&nbsp;buffer&nbsp;│&lt;—填入无用的数据&nbsp;<br>│&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;RET&nbsp;│&lt;—指向shellcode，或NOP指令的范围&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;NOP&nbsp;│&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&lt;—填入的NOP指令，是RET可指向的范围&nbsp;<br>│&nbsp;NOP&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;│&nbsp;<br>│&nbsp;shellcode&nbsp;│&nbsp;<br>│&nbsp;│&nbsp;<br>├———————┤&lt;—由exploit填入数据的结束&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&lt;—高端内存区域&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>windows下的动态数据除了可存放在栈中，还可以存放在堆中。了解C++的朋友都知道，C++可以使用new关键字来动态分配内存。来看下面的C++代码：&nbsp;</p>
<p style="FONT-FAMILY: Arial">#include&nbsp;&lt;stdio.h&gt;&nbsp;<br>#include&nbsp;&lt;iostream.h&gt;&nbsp;<br>#include&nbsp;&lt;windows.h&gt;&nbsp;</p>
<p style="FONT-FAMILY: Arial">void&nbsp;func()&nbsp;<br>{&nbsp;<br>char&nbsp;*buffer=new&nbsp;char[128];&nbsp;<br>char&nbsp;bufflocal[128];&nbsp;<br>static&nbsp;char&nbsp;buffstatic[128];&nbsp;<br>printf("0x%08x\n",buffer);&nbsp;//打印堆中变量的内存地址&nbsp;<br>printf("0x%08x\n",bufflocal);&nbsp;//打印本地变量的内存地址&nbsp;<br>printf("0x%08x\n",buffstatic);&nbsp;//打印静态变量的内存地址&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">void&nbsp;main()&nbsp;<br>{&nbsp;<br>func();&nbsp;<br>return;&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">程序执行结果为：&nbsp;</p>
<p style="FONT-FAMILY: Arial">0x004107d0&nbsp;<br>0x0012ff04&nbsp;<br>0x004068c0&nbsp;</p>
<p style="FONT-FAMILY: Arial">可以发现用new关键字分配的内存即不在栈中，也不在静态数据区。VC编译器是通过windows下的&#8220;堆(heap)&#8221;来实现new关键字的内存动态分配。在讲&#8220;堆&#8221;之前，先来了解一下和&#8220;堆&#8221;有关的几个API函数：&nbsp;</p>
<p style="FONT-FAMILY: Arial">HeapAlloc&nbsp;在堆中申请内存空间&nbsp;<br>HeapCreate&nbsp;创建一个新的堆对象&nbsp;<br>HeapDestroy&nbsp;销毁一个堆对象&nbsp;<br>HeapFree&nbsp;释放申请的内存&nbsp;<br>HeapWalk&nbsp;枚举堆对象的所有内存块&nbsp;<br>GetProcessHeap&nbsp;取得进程的默认堆对象&nbsp;<br>GetProcessHeaps&nbsp;取得进程所有的堆对象&nbsp;<br>LocalAlloc&nbsp;<br>GlobalAlloc&nbsp;</p>
<p style="FONT-FAMILY: Arial">当进程初始化时，系统会自动为进程创建一个默认堆，这个堆默认所占内存的大小为1M。堆对象由系统进行管理，它在内存中以链式结构存在。通过下面的代码可以通过堆动态申请内存空间：&nbsp;</p>
<p style="FONT-FAMILY: Arial">HANDLE&nbsp;hHeap=GetProcessHeap();&nbsp;<br>char&nbsp;*buff=HeapAlloc(hHeap,0,8);&nbsp;</p>
<p style="FONT-FAMILY: Arial">其中hHeap是堆对象的句柄，buff是指向申请的内存空间的地址。那这个hHeap究竟是什么呢？它的值有什么意义吗？看看下面这段代码吧：&nbsp;</p>
<p style="FONT-FAMILY: Arial">#pragma&nbsp;comment(linker,"/entry:main")&nbsp;//定义程序的入口&nbsp;<br>#include&nbsp;&lt;windows.h&gt;&nbsp;</p>
<p style="FONT-FAMILY: Arial">_CRTIMP&nbsp;int&nbsp;(__cdecl&nbsp;*printf)(const&nbsp;char&nbsp;*,&nbsp;...);&nbsp;//定义STL函数printf&nbsp;<br>/*---------------------------------------------------------------------------&nbsp;<br>写到这里，我们顺便来复习一下前面所讲的知识：&nbsp;<br>(*注)printf函数是C语言的标准函数库中函数，VC的标准函数库由msvcrt.dll模块实现。&nbsp;<br>由函数定义可见，printf的参数个数是可变的，函数内部无法预先知道调用者压入的参数个数，函数只能通过分析第一个参数字符串的格式来获得压入参数的信息，由于这里参数的个数是动态的，所以必须由调用者来平衡堆栈，这里便使用了__cdecl调用规则。BTW，Windows系统的API函数基本上是__stdcall调用形式，只有一个API例外，那就是wsprintf，它使用__cdecl调用规则，同printf函数一样，这是由于它的参数个数是可变的缘故。&nbsp;<br>---------------------------------------------------------------------------*/&nbsp;<br>void&nbsp;main()&nbsp;<br>{&nbsp;<br>HANDLE&nbsp;hHeap=GetProcessHeap();&nbsp;<br>char&nbsp;*buff=HeapAlloc(hHeap,0,0x10);&nbsp;<br>char&nbsp;*buff2=HeapAlloc(hHeap,0,0x10);&nbsp;<br>HMODULE&nbsp;hMsvcrt=LoadLibrary("msvcrt.dll");&nbsp;<br>printf=(void&nbsp;*)GetProcAddress(hMsvcrt,"printf");&nbsp;<br>printf("0x%08x\n",hHeap);&nbsp;<br>printf("0x%08x\n",buff);&nbsp;<br>printf("0x%08x\n\n",buff2);&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">执行结果为：&nbsp;</p>
<p style="FONT-FAMILY: Arial">0x00130000&nbsp;<br>0x00133100&nbsp;<br>0x00133118&nbsp;</p>
<p style="FONT-FAMILY: Arial">hHeap的值怎么和那个buff的值那么接近呢？其实hHeap这个句柄就是指向HEAP首部的地址。在进程的用户区存着一个叫PEB(进程环境块)的结构，这个结构中存放着一些有关进程的重要信息，其中在PEB首地址偏移0x18处存放的ProcessHeap就是进程默认堆的地址，而偏移0x90处存放了指向进程所有堆的地址列表的指针。windows有很多API都使用进程的默认堆来存放动态数据，如windows&nbsp;2000下的所有ANSI版本的函数都是在默认堆中申请内存来转换ANSI字符串到Unicode字符串的。对一个堆的访问是顺序进行的，同一时刻只能有一个线程访问堆中的数据，当多个线程同时有访问要求时，只能排队等待，这样便造成程序执行效率下降。&nbsp;</p>
<p style="FONT-FAMILY: Arial">最后来说说内存中的数据对齐。所位数据对齐，是指数据所在的内存地址必须是该数据长度的整数倍，DWORD数据的内存起始地址能被4除尽，WORD数据的内存起始地址能被2除尽，x86&nbsp;CPU能直接访问对齐的数据，当他试图访问一个未对齐的数据时，会在内部进行一系列的调整，这些调整对于程序来说是透明的，但是会降低运行速度，所以编译器在编译程序时会尽量保证数据对齐。同样一段代码，我们来看看用VC、Dev-C++和lcc三个不同编译器编译出来的程序的执行结果：&nbsp;</p>
<p style="FONT-FAMILY: Arial">#include&nbsp;&lt;stdio.h&gt;&nbsp;</p>
<p style="FONT-FAMILY: Arial">int&nbsp;main()&nbsp;<br>{&nbsp;<br>int&nbsp;a;&nbsp;<br>char&nbsp;b;&nbsp;<br>int&nbsp;c;&nbsp;<br>printf("0x%08x\n",&amp;a);&nbsp;<br>printf("0x%08x\n",&amp;b);&nbsp;<br>printf("0x%08x\n",&amp;c);&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p style="FONT-FAMILY: Arial">这是用VC编译后的执行结果：&nbsp;<br>0x0012ff7c&nbsp;<br>0x0012ff7b&nbsp;<br>0x0012ff80&nbsp;<br>变量在内存中的顺序：b(1字节)-a(4字节)-c(4字节)。&nbsp;</p>
<p style="FONT-FAMILY: Arial">这是用Dev-C++编译后的执行结果：&nbsp;<br>0x0022ff7c&nbsp;<br>0x0022ff7b&nbsp;<br>0x0022ff74&nbsp;<br>变量在内存中的顺序：c(4字节)-中间相隔3字节-b(占1字节)-a(4字节)。&nbsp;</p>
<p style="FONT-FAMILY: Arial">这是用lcc编译后的执行结果：&nbsp;<br>0x0012ff6c&nbsp;<br>0x0012ff6b&nbsp;<br>0x0012ff64&nbsp;<br>变量在内存中的顺序：同上。&nbsp;</p>
<p style="FONT-FAMILY: Arial">三个编译器都做到了数据对齐，但是后两个编译器显然没VC&#8220;聪明&#8221;，让一个char占了4字节，浪费内存哦。&nbsp;</p>
<p style="FONT-FAMILY: Arial"><br>基础知识：&nbsp;<br>堆栈是一种简单的数据结构，是一种只允许在其一端进行插入或删除的线性表。允许插入或删除操作的一端称为栈顶，另一端称为栈底，对堆栈的插入和删除操作被称为入栈和出栈。有一组CPU指令可以实现对进程的内存实现堆栈访问。其中，POP指令实现出栈操作，PUSH指令实现入栈操作。CPU的ESP寄存器存放当前线程的栈顶指针，EBP寄存器中保存当前线程的栈底指针。CPU的EIP寄存器存放下一个CPU指令存放的内存地址，当CPU执行完当前的指令后，从EIP寄存器中读取下一条指令的内存地址，然后继续执行。&nbsp;<br><br>参考：《Windows下的HEAP溢出及其利用》by:&nbsp;isno&nbsp;<br>《windows核心编程》by:&nbsp;Jeffrey&nbsp;Richter&nbsp;</p>
<p style="FONT-FAMILY: Arial">摘要：&nbsp;讨论常见的堆性能问题以及如何防范它们。（共&nbsp;9&nbsp;页）</p>
<p style="FONT-FAMILY: Arial">前言<br>您是否是动态分配的&nbsp;C/C++&nbsp;对象忠实且幸运的用户？您是否在模块间的往返通信中频繁地使用了&#8220;自动化&#8221;？您的程序是否因堆分配而运行起来很慢？不仅仅您遇到这样的问题。几乎所有项目迟早都会遇到堆问题。大家都想说，&#8220;我的代码真正好，只是堆太慢&#8221;。那只是部分正确。更深入理解堆及其用法、以及会发生什么问题，是很有用的。</p>
<p style="FONT-FAMILY: Arial">什么是堆？<br>（如果您已经知道什么是堆，可以跳到&#8220;什么是常见的堆性能问题？&#8221;部分）</p>
<p style="FONT-FAMILY: Arial">在程序中，使用堆来动态分配和释放对象。在下列情况下，调用堆操作：&nbsp;</p>
<p style="FONT-FAMILY: Arial">事先不知道程序所需对象的数量和大小。</p>
<p style="FONT-FAMILY: Arial"><br>对象太大而不适合堆栈分配程序。<br>堆使用了在运行时分配给代码和堆栈的内存之外的部分内存。下图给出了堆分配程序的不同层。</p>
<p style="FONT-FAMILY: Arial">GlobalAlloc/GlobalFree：Microsoft&nbsp;Win32&nbsp;堆调用，这些调用直接与每个进程的默认堆进行对话。</p>
<p style="FONT-FAMILY: Arial">LocalAlloc/LocalFree：Win32&nbsp;堆调用（为了与&nbsp;Microsoft&nbsp;Windows&nbsp;NT&nbsp;兼容），这些调用直接与每个进程的默认堆进行对话。</p>
<p style="FONT-FAMILY: Arial">COM&nbsp;的&nbsp;IMalloc&nbsp;分配程序（或&nbsp;CoTaskMemAlloc&nbsp;/&nbsp;CoTaskMemFree）：函数使用每个进程的默认堆。自动化程序使用&#8220;组件对象模型&nbsp;(COM)&#8221;的分配程序，而申请的程序使用每个进程堆。</p>
<p style="FONT-FAMILY: Arial">C/C++&nbsp;运行时&nbsp;(CRT)&nbsp;分配程序：提供了&nbsp;malloc()&nbsp;和&nbsp;free()&nbsp;以及&nbsp;new&nbsp;和&nbsp;delete&nbsp;操作符。如&nbsp;Microsoft&nbsp;Visual&nbsp;Basic&nbsp;和&nbsp;Java&nbsp;等语言也提供了新的操作符并使用垃圾收集来代替堆。CRT&nbsp;创建自己的私有堆，驻留在&nbsp;Win32&nbsp;堆的顶部。</p>
<p style="FONT-FAMILY: Arial">Windows&nbsp;NT&nbsp;中，Win32&nbsp;堆是&nbsp;Windows&nbsp;NT&nbsp;运行时分配程序周围的薄层。所有&nbsp;API&nbsp;转发它们的请求给&nbsp;NTDLL。</p>
<p style="FONT-FAMILY: Arial">Windows&nbsp;NT&nbsp;运行时分配程序提供&nbsp;Windows&nbsp;NT&nbsp;内的核心堆分配程序。它由具有&nbsp;128&nbsp;个大小从&nbsp;8&nbsp;到&nbsp;1,024&nbsp;字节的空闲列表的前端分配程序组成。后端分配程序使用虚拟内存来保留和提交页。</p>
<p style="FONT-FAMILY: Arial">在图表的底部是&#8220;虚拟内存分配程序&#8221;，操作系统使用它来保留和提交页。所有分配程序使用虚拟内存进行数据的存取。</p>
<p style="FONT-FAMILY: Arial">分配和释放块不就那么简单吗？为何花费这么长时间？</p>
<p style="FONT-FAMILY: Arial">堆实现的注意事项<br>传统上，操作系统和运行时库是与堆的实现共存的。在一个进程的开始，操作系统创建一个默认堆，叫做&#8220;进程堆&#8221;。如果没有其他堆可使用，则块的分配使用&#8220;进程堆&#8221;。语言运行时也能在进程内创建单独的堆。（例如，C&nbsp;运行时创建它自己的堆。）除这些专用的堆外，应用程序或许多已载入的动态链接库&nbsp;(DLL)&nbsp;之一可以创建和使用单独的堆。Win32&nbsp;提供一整套&nbsp;API&nbsp;来创建和使用私有堆。有关堆函数（英文）的详尽指导，请参见&nbsp;MSDN。</p>
<p style="FONT-FAMILY: Arial">当应用程序或&nbsp;DLL&nbsp;创建私有堆时，这些堆存在于进程空间，并且在进程内是可访问的。从给定堆分配的数据将在同一个堆上释放。（不能从一个堆分配而在另一个堆释放。）</p>
<p style="FONT-FAMILY: Arial">在所有虚拟内存系统中，堆驻留在操作系统的&#8220;虚拟内存管理器&#8221;的顶部。语言运行时堆也驻留在虚拟内存顶部。某些情况下，这些堆是操作系统堆中的层，而语言运行时堆则通过大块的分配来执行自己的内存管理。不使用操作系统堆，而使用虚拟内存函数更利于堆的分配和块的使用。</p>
<p style="FONT-FAMILY: Arial">典型的堆实现由前、后端分配程序组成。前端分配程序维持固定大小块的空闲列表。对于一次分配调用，堆尝试从前端列表找到一个自由块。如果失败，堆被迫从后端（保留和提交虚拟内存）分配一个大块来满足请求。通用的实现有每块分配的开销，这将耗费执行周期，也减少了可使用的存储空间。</p>
<p style="FONT-FAMILY: Arial">Knowledge&nbsp;Base&nbsp;文章&nbsp;Q10758，&#8220;用&nbsp;calloc()&nbsp;和&nbsp;malloc()&nbsp;管理内存&#8221;&nbsp;（搜索文章编号）,&nbsp;包含了有关这些主题的更多背景知识。另外，有关堆实现和设计的详细讨论也可在下列著作中找到：&#8220;Dynamic&nbsp;Storage&nbsp;Allocation:&nbsp;A&nbsp;Survey&nbsp;and&nbsp;Critical&nbsp;Review&#8221;，作者&nbsp;Paul&nbsp;R.&nbsp;Wilson、Mark&nbsp;S.&nbsp;Johnstone、Michael&nbsp;Neely&nbsp;和&nbsp;David&nbsp;Boles；&#8220;International&nbsp;Workshop&nbsp;on&nbsp;Memory&nbsp;Management&#8221;,&nbsp;作者&nbsp;Kinross,&nbsp;Scotland,&nbsp;UK,&nbsp;1995&nbsp;年&nbsp;9&nbsp;月(<img src="http://club.5ivb.net/pic/url.gif" align=absMiddle border=0><a href="http://www.cs.utexas.edu/users/oops/papers.html" target=_blank><font color=#000000><u>http://www.cs.utexas.edu/users/oops/papers.html</u></font></a>)（英文）。</p>
<p style="FONT-FAMILY: Arial">Windows&nbsp;NT&nbsp;的实现（Windows&nbsp;NT&nbsp;版本&nbsp;4.0&nbsp;和更新版本）&nbsp;使用了&nbsp;127&nbsp;个大小从&nbsp;8&nbsp;到&nbsp;1,024&nbsp;字节的&nbsp;8&nbsp;字节对齐块空闲列表和一个&#8220;大块&#8221;列表。&#8220;大块&#8221;列表（空闲列表[0]）&nbsp;保存大于&nbsp;1,024&nbsp;字节的块。空闲列表容纳了用双向链表链接在一起的对象。默认情况下，&#8220;进程堆&#8221;执行收集操作。（收集是将相邻空闲块合并成一个大块的操作。）收集耗费了额外的周期，但减少了堆块的内部碎片。</p>
<p style="FONT-FAMILY: Arial">单一全局锁保护堆，防止多线程式的使用。（请参见&#8220;Server&nbsp;Performance&nbsp;and&nbsp;Scalability&nbsp;Killers&#8221;中的第一个注意事项,&nbsp;George&nbsp;Reilly&nbsp;所著，在&nbsp;&#8220;MSDN&nbsp;Online&nbsp;Web&nbsp;Workshop&#8221;上（站点：<img src="http://club.5ivb.net/pic/url.gif" align=absMiddle border=0><a href="http://msdn.microsoft.com/workshop/server/iis/tencom.asp" target=_blank><font color=#000000><u>http://msdn.microsoft.com/workshop/server/iis/tencom.asp</u></font></a>（英文）。）单一全局锁本质上是用来保护堆数据结构，防止跨多线程的随机存取。若堆操作太频繁，单一全局锁会对性能有不利的影响。</p>
<p style="FONT-FAMILY: Arial">什么是常见的堆性能问题？<br>以下是您使用堆时会遇到的最常见问题：&nbsp;</p>
<p style="FONT-FAMILY: Arial">分配操作造成的速度减慢。光分配就耗费很长时间。最可能导致运行速度减慢原因是空闲列表没有块，所以运行时分配程序代码会耗费周期寻找较大的空闲块，或从后端分配程序分配新块。</p>
<p style="FONT-FAMILY: Arial"><br>释放操作造成的速度减慢。释放操作耗费较多周期，主要是启用了收集操作。收集期间，每个释放操作&#8220;查找&#8221;它的相邻块，取出它们并构造成较大块，然后再把此较大块插入空闲列表。在查找期间，内存可能会随机碰到，从而导致高速缓存不能命中，性能降低。</p>
<p style="FONT-FAMILY: Arial"><br>堆竞争造成的速度减慢。当两个或多个线程同时访问数据，而且一个线程继续进行之前必须等待另一个线程完成时就发生竞争。竞争总是导致麻烦；这也是目前多处理器系统遇到的最大问题。当大量使用内存块的应用程序或&nbsp;DLL&nbsp;以多线程方式运行（或运行于多处理器系统上）时将导致速度减慢。单一锁定的使用—常用的解决方案—意味着使用堆的所有操作是序列化的。当等待锁定时序列化会引起线程切换上下文。可以想象交叉路口闪烁的红灯处走走停停导致的速度减慢。&nbsp;<br>竞争通常会导致线程和进程的上下文切换。上下文切换的开销是很大的，但开销更大的是数据从处理器高速缓存中丢失，以及后来线程复活时的数据重建。</p>
<p style="FONT-FAMILY: Arial">堆破坏造成的速度减慢。造成堆破坏的原因是应用程序对堆块的不正确使用。通常情形包括释放已释放的堆块或使用已释放的堆块，以及块的越界重写等明显问题。（破坏不在本文讨论范围之内。有关内存重写和泄漏等其他细节，请参见&nbsp;Microsoft&nbsp;Visual&nbsp;C++(R)&nbsp;调试文档&nbsp;。）</p>
<p style="FONT-FAMILY: Arial"><br>频繁的分配和重分配造成的速度减慢。这是使用脚本语言时非常普遍的现象。如字符串被反复分配，随重分配增长和释放。不要这样做，如果可能，尽量分配大字符串和使用缓冲区。另一种方法就是尽量少用连接操作。<br>竞争是在分配和释放操作中导致速度减慢的问题。理想情况下，希望使用没有竞争和快速分配/释放的堆。可惜，现在还没有这样的通用堆，也许将来会有。</p>
<p style="FONT-FAMILY: Arial">在所有的服务器系统中（如&nbsp;IIS、MSProxy、DatabaseStacks、网络服务器、&nbsp;Exchange&nbsp;和其他）,&nbsp;堆锁定实在是个大瓶颈。处理器数越多，竞争就越会恶化。</p>
<p style="FONT-FAMILY: Arial">尽量减少堆的使用<br>现在您明白使用堆时存在的问题了，难道您不想拥有能解决这些问题的超级魔棒吗？我可希望有。但没有魔法能使堆运行加快—因此不要期望在产品出货之前的最后一星期能够大为改观。如果提前规划堆策略，情况将会大大好转。调整使用堆的方法，减少对堆的操作是提高性能的良方。</p>
<p style="FONT-FAMILY: Arial">如何减少使用堆操作？通过利用数据结构内的位置可减少堆操作的次数。请考虑下列实例：</p>
<p style="FONT-FAMILY: Arial">struct&nbsp;ObjectA&nbsp;{<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectA&nbsp;的数据&nbsp;<br>}</p>
<p style="FONT-FAMILY: Arial">struct&nbsp;ObjectB&nbsp;{<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectB&nbsp;的数据&nbsp;<br>}</p>
<p style="FONT-FAMILY: Arial">//&nbsp;同时使用&nbsp;objectA&nbsp;和&nbsp;objectB</p>
<p style="FONT-FAMILY: Arial">//<br>//&nbsp;使用指针&nbsp;<br>//<br>struct&nbsp;ObjectB&nbsp;{<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectA&nbsp;*&nbsp;pObjA;<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectB&nbsp;的数据&nbsp;<br>}</p>
<p style="FONT-FAMILY: Arial">//<br>//&nbsp;使用嵌入<br>//<br>struct&nbsp;ObjectB&nbsp;{<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectA&nbsp;pObjA;<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectB&nbsp;的数据&nbsp;<br>}</p>
<p style="FONT-FAMILY: Arial">//<br>//&nbsp;集合&nbsp;&#8211;&nbsp;在另一对象内使用&nbsp;objectA&nbsp;和&nbsp;objectB<br>//</p>
<p style="FONT-FAMILY: Arial">struct&nbsp;ObjectX&nbsp;{<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectA&nbsp;&nbsp;objA;<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectB&nbsp;&nbsp;objB;<br>}</p>
<p style="FONT-FAMILY: Arial">避免使用指针关联两个数据结构。如果使用指针关联两个数据结构，前面实例中的对象&nbsp;A&nbsp;和&nbsp;B&nbsp;将被分别分配和释放。这会增加额外开销—我们要避免这种做法。</p>
<p style="FONT-FAMILY: Arial"><br>把带指针的子对象嵌入父对象。当对象中有指针时，则意味着对象中有动态元素（百分之八十）和没有引用的新位置。嵌入增加了位置从而减少了进一步分配/释放的需求。这将提高应用程序的性能。</p>
<p style="FONT-FAMILY: Arial"><br>合并小对象形成大对象（聚合）。聚合减少分配和释放的块的数量。如果有几个开发者，各自开发设计的不同部分，则最终会有许多小对象需要合并。集成的挑战就是要找到正确的聚合边界。</p>
<p style="FONT-FAMILY: Arial"><br>内联缓冲区能够满足百分之八十的需要（aka&nbsp;80-20&nbsp;规则）。个别情况下，需要内存缓冲区来保存字符串/二进制数据，但事先不知道总字节数。估计并内联一个大小能满足百分之八十需要的缓冲区。对剩余的百分之二十，可以分配一个新的缓冲区和指向这个缓冲区的指针。这样，就减少分配和释放调用并增加数据的位置空间，从根本上提高代码的性能。</p>
<p style="FONT-FAMILY: Arial"><br>在块中分配对象（块化）。块化是以组的方式一次分配多个对象的方法。如果对列表的项连续跟踪，例如对一个&nbsp;{名称，值}&nbsp;对的列表，有两种选择：选择一是为每一个&#8220;名称-值&#8221;对分配一个节点；选择二是分配一个能容纳（如五个）&#8220;名称-值&#8221;对的结构。例如，一般情况下，如果存储四对，就可减少节点的数量，如果需要额外的空间数量，则使用附加的链表指针。&nbsp;<br>块化是友好的处理器高速缓存，特别是对于&nbsp;L1-高速缓存，因为它提供了增加的位置&nbsp;—不用说对于块分配，很多数据块会在同一个虚拟页中。</p>
<p style="FONT-FAMILY: Arial">正确使用&nbsp;_amblksiz。C&nbsp;运行时&nbsp;(CRT)&nbsp;有它的自定义前端分配程序，该分配程序从后端（Win32&nbsp;堆）分配大小为&nbsp;_amblksiz&nbsp;的块。将&nbsp;_amblksiz&nbsp;设置为较高的值能潜在地减少对后端的调用次数。这只对广泛使用&nbsp;CRT&nbsp;的程序适用。<br>使用上述技术将获得的好处会因对象类型、大小及工作量而有所不同。但总能在性能和可升缩性方面有所收获。另一方面，代码会有点特殊，但如果经过深思熟虑，代码还是很容易管理的。</p>
<p style="FONT-FAMILY: Arial">其他提高性能的技术<br>下面是一些提高速度的技术：&nbsp;</p>
<p style="FONT-FAMILY: Arial">使用&nbsp;Windows&nbsp;NT5&nbsp;堆&nbsp;<br>由于几个同事的努力和辛勤工作，1998&nbsp;年初&nbsp;Microsoft&nbsp;Windows(R)&nbsp;2000&nbsp;中有了几个重大改进：</p>
<p style="FONT-FAMILY: Arial">改进了堆代码内的锁定。堆代码对每堆一个锁。全局锁保护堆数据结构，防止多线程式的使用。但不幸的是，在高通信量的情况下，堆仍受困于全局锁，导致高竞争和低性能。Windows&nbsp;2000&nbsp;中，锁内代码的临界区将竞争的可能性减到最小,从而提高了可伸缩性。</p>
<p style="FONT-FAMILY: Arial"><br>使用&nbsp;&#8220;Lookaside&#8221;列表。堆数据结构对块的所有空闲项使用了大小在&nbsp;8&nbsp;到&nbsp;1,024&nbsp;字节（以&nbsp;8-字节递增）的快速高速缓存。快速高速缓存最初保护在全局锁内。现在，使用&nbsp;lookaside&nbsp;列表来访问这些快速高速缓存空闲列表。这些列表不要求锁定，而是使用&nbsp;64&nbsp;位的互锁操作，因此提高了性能。</p>
<p style="FONT-FAMILY: Arial"><br>内部数据结构算法也得到改进。<br>这些改进避免了对分配高速缓存的需求，但不排除其他的优化。使用&nbsp;Windows&nbsp;NT5&nbsp;堆评估您的代码；它对小于&nbsp;1,024&nbsp;字节&nbsp;(1&nbsp;KB)&nbsp;的块（来自前端分配程序的块）是最佳的。GlobalAlloc()&nbsp;和&nbsp;LocalAlloc()&nbsp;建立在同一堆上，是存取每个进程堆的通用机制。如果希望获得高的局部性能，则使用&nbsp;Heap(R)&nbsp;API&nbsp;来存取每个进程堆，或为分配操作创建自己的堆。如果需要对大块操作，也可以直接使用&nbsp;VirtualAlloc()&nbsp;/&nbsp;VirtualFree()&nbsp;操作。</p>
<p style="FONT-FAMILY: Arial">上述改进已在&nbsp;Windows&nbsp;2000&nbsp;beta&nbsp;2&nbsp;和&nbsp;Windows&nbsp;NT&nbsp;4.0&nbsp;SP4&nbsp;中使用。改进后，堆锁的竞争率显著降低。这使所有&nbsp;Win32&nbsp;堆的直接用户受益。CRT&nbsp;堆建立于&nbsp;Win32&nbsp;堆的顶部，但它使用自己的小块堆，因而不能从&nbsp;Windows&nbsp;NT&nbsp;改进中受益。（Visual&nbsp;C++&nbsp;版本&nbsp;6.0&nbsp;也有改进的堆分配程序。）</p>
<p style="FONT-FAMILY: Arial">使用分配高速缓存&nbsp;<br>分配高速缓存允许高速缓存分配的块，以便将来重用。这能够减少对进程堆（或全局堆）的分配/释放调用的次数，也允许最大限度的重用曾经分配的块。另外，分配高速缓存允许收集统计信息,以便较好地理解对象在较高层次上的使用。</p>
<p style="FONT-FAMILY: Arial">典型地，自定义堆分配程序在进程堆的顶部实现。自定义堆分配程序与系统堆的行为很相似。主要的差别是它在进程堆的顶部为分配的对象提供高速缓存。高速缓存设计成一套固定大小（如&nbsp;32&nbsp;字节、64&nbsp;字节、128&nbsp;字节等）。这一个很好的策略，但这种自定义堆分配程序丢失与分配和释放的对象相关的&#8220;语义信息&#8221;。&nbsp;</p>
<p style="FONT-FAMILY: Arial">与自定义堆分配程序相反，&#8220;分配高速缓存&#8221;作为每类分配高速缓存来实现。除能够提供自定义堆分配程序的所有好处之外，它们还能够保留大量语义信息。每个分配高速缓存处理程序与一个目标二进制对象关联。它能够使用一套参数进行初始化，这些参数表示并发级别、对象大小和保持在空闲列表中的元素的数量等。分配高速缓存处理程序对象维持自己的私有空闲实体池（不超过指定的阀值）并使用私有保护锁。合在一起，分配高速缓存和私有锁减少了与主系统堆的通信量，因而提供了增加的并发、最大限度的重用和较高的可伸缩性。</p>
<p style="FONT-FAMILY: Arial">需要使用清理程序来定期检查所有分配高速缓存处理程序的活动情况并回收未用的资源。如果发现没有活动，将释放分配对象的池，从而提高性能。</p>
<p style="FONT-FAMILY: Arial">可以审核每个分配/释放活动。第一级信息包括对象、分配和释放调用的总数。通过查看它们的统计信息可以得出各个对象之间的语义关系。利用以上介绍的许多技术之一，这种关系可以用来减少内存分配。</p>
<p style="FONT-FAMILY: Arial">分配高速缓存也起到了调试助手的作用，帮助您跟踪没有完全清除的对象数量。通过查看动态堆栈返回踪迹和除没有清除的对象之外的签名，甚至能够找到确切的失败的调用者。</p>
<p style="FONT-FAMILY: Arial">MP&nbsp;堆&nbsp;<br>MP&nbsp;堆是对多处理器友好的分布式分配的程序包，在&nbsp;Win32&nbsp;SDK（Windows&nbsp;NT&nbsp;4.0&nbsp;和更新版本）中可以得到。最初由&nbsp;JVert&nbsp;实现，此处堆抽象建立在&nbsp;Win32&nbsp;堆程序包的顶部。MP&nbsp;堆创建多个&nbsp;Win32&nbsp;堆，并试图将分配调用分布到不同堆，以减少在所有单一锁上的竞争。</p>
<p style="FONT-FAMILY: Arial">本程序包是好的步骤&nbsp;—一种改进的&nbsp;MP-友好的自定义堆分配程序。但是，它不提供语义信息和缺乏统计功能。通常将&nbsp;MP&nbsp;堆作为&nbsp;SDK&nbsp;库来使用。如果使用这个&nbsp;SDK&nbsp;创建可重用组件，您将大大受益。但是，如果在每个&nbsp;DLL&nbsp;中建立这个&nbsp;SDK&nbsp;库，将增加工作设置。</p>
<p style="FONT-FAMILY: Arial">重新思考算法和数据结构&nbsp;<br>要在多处理器机器上伸缩，则算法、实现、数据结构和硬件必须动态伸缩。请看最经常分配和释放的数据结构。试问，&#8220;我能用不同的数据结构完成此工作吗？&#8221;例如，如果在应用程序初始化时加载了只读项的列表，这个列表不必是线性链接的列表。如果是动态分配的数组就非常好。动态分配的数组将减少内存中的堆块和碎片，从而增强性能。</p>
<p style="FONT-FAMILY: Arial">减少需要的小对象的数量减少堆分配程序的负载。例如，我们在服务器的关键处理路径上使用五个不同的对象，每个对象单独分配和释放。一起高速缓存这些对象，把堆调用从五个减少到一个，显著减少了堆的负载，特别当每秒钟处理&nbsp;1,000&nbsp;个以上的请求时。</p>
<p style="FONT-FAMILY: Arial">如果大量使用&#8220;Automation&#8221;结构，请考虑从主线代码中删除&#8220;Automation&nbsp;BSTR&#8221;，或至少避免重复的&nbsp;BSTR&nbsp;操作。（BSTR&nbsp;连接导致过多的重分配和分配/释放操作。）</p>
<p style="FONT-FAMILY: Arial">摘要<br>对所有平台往往都存在堆实现，因此有巨大的开销。每个单独代码都有特定的要求，但设计能采用本文讨论的基本理论来减少堆之间的相互作用。&nbsp;</p>
<p style="FONT-FAMILY: Arial">评价您的代码中堆的使用。</p>
<p style="FONT-FAMILY: Arial"><br>改进您的代码，以使用较少的堆调用：分析关键路径和固定数据结构。</p>
<p style="FONT-FAMILY: Arial"><br>在实现自定义的包装程序之前使用量化堆调用成本的方法。</p>
<p style="FONT-FAMILY: Arial"><br>如果对性能不满意，请要求&nbsp;OS&nbsp;组改进堆。更多这类请求意味着对改进堆的更多关注。</p>
<p style="FONT-FAMILY: Arial"><br>要求&nbsp;C&nbsp;运行时组针对&nbsp;OS&nbsp;所提供的堆制作小巧的分配包装程序。随着&nbsp;OS&nbsp;堆的改进，C&nbsp;运行时堆调用的成本将减小。</p>
<p style="FONT-FAMILY: Arial"><br>操作系统（Windows&nbsp;NT&nbsp;家族）正在不断改进堆。请随时关注和利用这些改进。<br>Murali&nbsp;Krishnan&nbsp;是&nbsp;Internet&nbsp;Information&nbsp;Server&nbsp;(IIS)&nbsp;组的首席软件设计工程师。从&nbsp;1.0&nbsp;版本开始他就设计&nbsp;IIS，并成功发行了&nbsp;1.0&nbsp;版本到&nbsp;4.0&nbsp;版本。Murali&nbsp;组织并领导&nbsp;IIS&nbsp;性能组三年&nbsp;(1995-1998),&nbsp;从一开始就影响&nbsp;IIS&nbsp;性能。他拥有威斯康星州&nbsp;Madison&nbsp;大学的&nbsp;M.S.和印度&nbsp;Anna&nbsp;大学的&nbsp;B.S.。工作之外，他喜欢阅读、打排球和家庭烹饪</p>
</div>
<img src ="http://www.cnitblog.com/benwhite/aggbug/25160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2007-04-04 16:43 <a href="http://www.cnitblog.com/benwhite/archive/2007/04/04/25160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>windows--编译LinQ(开源的即时通信客户端)源代码</title><link>http://www.cnitblog.com/benwhite/archive/2007/02/02/22589.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Fri, 02 Feb 2007 13:42:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2007/02/02/22589.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/22589.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2007/02/02/22589.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/22589.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/22589.html</trackback:ping><description><![CDATA[
		<p>因为LinQ 的Source是使用mingw编译的 并且使用了QT &amp; win32 OpenSSL 因此我们先需下载这些软件</p>
		<p>参考LinQ编译说明网页 <a href="http://linq.sourceforge.net/compile.php">http://linq.sourceforge.net/compile.php</a><br />1 安装minGW &amp; MSYS 环境<br />MinGw 是Minimalist GNU on Windows缩写 它是一些头文件和端口库的集合，该集合允许人们在没有第三方动态链接库的情况下使用 GCC（GNU Compiler C）产生 Windows32 程序。  <br />开发 MinGW 是为了那些不喜欢工作在 Linux(FreeBSD) 操作系统而留在 Windows 的人提供一套符合 GNU 的 GNU 工作环境。</p>
		<p>MSYS Minimal GNU（POSIX）system on Windows，是一个小型的GNU环境，包括基本的ls bash，make等等。是Windows下最优秀的GNU环境</p>
		<p>下载安装:<br />minGW 5.0.2.exe 很小 安装过程会去下载相应的实体,主要包括 <br /> binutils-2.16.91-20060119-1.tar.gz<br /> gcc-core-3.4.2-20040916-1.tar.gz<br /> mingw32-make-3.81-1.tar.gz <br /> mingw-runtime-3.11.tar.gz<br /> w32api-3.8.tar.gz<br />(速度超慢~~) 下载完成后 安装在 C:/MinGW即可</p>
		<p>MSYS1.0.10.exe 直接安装C:/MSYS下即可 要在minGW安装之后</p>
		<p>2 安装QT<br />下载qt-win-opensource-4.2.2-mingw.exe 安装在C盘 中间要求确定MinGW的安装位置 指定即可 有点大 100多M</p>
		<p>3 安装OpenSSL 按照LinQ网站说明 要安装在D:\OpenSSL 想必是工程里使用了绝对路径 <br />  还有可能要改名:rename ssleay32.a to libssleay32.a if necessary.(ssleay32.a在D:\OpenSSL\lib\MinGW)</p>
		<p>4 打开MSYS窗口 输入:configure --enable-debug</p>
		<p>5 打开cmd窗口  转入linq的文件夹<br />       先输入 qmake 再输入 mingw32-make</p>
		<p>Good Luck!<br />可惜我没有成功 [error   ld.exe: cannot find -lQtXmld4] -_-bb</p>
		<p>当然原因是QT的问题 没有找到 QtXmld4.dll <br />搜索原因 后发现QT安装时 并没有给全库文件 需要configure 和qmake <br />见安装目录的INSTALL文件:<br />/************************************************************/<br />To configure the Qt library for your machine type:</p>
		<p>        C:<br />        cd \Qt\4.2.2<br />        configure<br />  mingw32-make   <br />/************************************************************/<br />根据环境产生qmake程序，然后在rebuild所有的Qt源文件,demo,examples,tools,plugins<br />这步超长 我用了近5个小时 而且文件大小急遽变大 有 2个多G 汗~~</p>
		<p>终于生成了完整的库 然后重做 4,5步 成功!!!<br />从3M 生成160M <br />生成的linq.exe就在C:/linq下 运行 OK~~<br />[与安装版不同的是 运行后还有控制台 可以直接查看XML流 !]</p>
		<p>
				<br />2007-02-01 22:40 benwhite<br /></p>
<img src ="http://www.cnitblog.com/benwhite/aggbug/22589.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2007-02-02 21:42 <a href="http://www.cnitblog.com/benwhite/archive/2007/02/02/22589.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于apache php mysql的配置</title><link>http://www.cnitblog.com/benwhite/archive/2006/12/12/20420.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Tue, 12 Dec 2006 12:59:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2006/12/12/20420.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/20420.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2006/12/12/20420.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/20420.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/20420.html</trackback:ping><description><![CDATA[很多人混乱于配置仅仅是因为他们没有耐心读文档，其实在每个apache，php安装文件夹的install.txt 中都有详细的说明，只不过因为是英文，于是很多人没有耐心看而已。<br />well 下面说说配置，很简单，就几步：<br />1 安装Apache ，然后可以设置自己的网页目录如：DocumentRoot "C:/Program Files/Apache2/htdocs"，<br />   然后先停止Apache服务器。<br />2 安装PHP，简单一点就安在C盘下。然后打开install.txt 找到“Installing as a CGI binary”<br />后面讲到：在Apache下使用PHP的两种方式：作为CGI 二进制 或者 作为Apache的模块<br />分别将对应的代码复制到apache的httpd.conf即可。重启apache。<br />如果要使用mysql 则在php.ini 中激活 php_mysql.dll 扩展库。首先是去掉;extension=php_mysql.dll前面的“;”（;为注释），第二步是将C:\php\ext中的php_mysql.dll复制到C:\WINDOWS（C:\WINNT）中即可，或者将环境变量的PATH值增加;C:\php\ext。<br />3 安装mysql。没啥可讲的，一步步设置好即可。<br /><br />就这么简单！<br /><strong>以上针对PHP5+Apache2+Mysql5版本</strong><br /><br />一下转载：<br /><h4>软件的安装</h4><p><b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Apache</b>和MySQL可以下载安装文件，像安装普通软件一样操作；php则下载压缩包解压即可。建议安装目录结构层次清晰，名字简单。比如在某个分区X下建X:\<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">apache</b>、X:\php、X:\mysql三个目录。</p><h4><b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Apache</b>的基本配置</h4><p>修改httpd.Conf文件。<br />DocumentRoot指定网站根目录。比如X:\htdocs。默认的如果觉得可以不改也行。<br />DirectoryIndex指定目录默认首页读取的文件类型和顺序。如果要支持php，可加入index.php等。可以任意加文件名和调整顺序。</p><h4>PHP的基本配置</h4><p>以php5为例，所谓php的安装配置，无非是要让服务器读取以下三个文件（以模块方式；附带文档不推荐cgi方式，不做介绍）：php.ini、php5ts.dll和php5<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">apache</b>2.dll。下面介绍的方法不用复制转移任何一个文件，有利于升级维护，是附带按装文档所推荐的。<br />php.ini的读取：在<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Apache</b>的httpd.Conf添加：<strong><coolcoolcode>PHPIniDir “php文件夹<a name="baidusnap1"></a><b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">路径</b>”</coolcoolcode></strong>。<br />php5ts.dll的读取：在系统变量Path添加：<strong><coolcoolcode>;php文件夹<b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">路径</b></coolcoolcode></strong>，或者在<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Apache</b>的httpd.Conf中添加：<strong><coolcoolcode>LoadFile “php5ts.dll的<b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">路径</b>”</coolcoolcode></strong>。<br />php5<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">apache</b>2.dll的读取：在<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Apache</b>的httpd.Conf中添加<strong>：<coolcoolcode>LoadMoudule php5_module “php文件夹<b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">路径</b>”</coolcoolcode></strong>。</p><h4>MySQL的基本配置</h4><p>Instance Config Wizard能够完成主要的配置，不需要编辑其他文件了。在php.ini中则要做以下修改，使php支持mysql：<br />1、把<strong><coolcoolcode>;extension=php_mysql.dll</coolcoolcode></strong>的开头的分号去掉，加载mysql功能。<br />2、告诉php.ini要加载的dll文件在哪里：修改<strong><coolcoolcode>extension_dir = </coolcoolcode></strong>为<strong><coolcoolcode>extension_dir = php文件夹\ext</coolcoolcode></strong>，或者在系统变量Path添加：<strong><coolcoolcode>;php文件夹\ext</coolcoolcode></strong>。<br />（ext是php文件夹里面默认的dll文件所在文件夹。）</p><h4>其他</h4><p>注意，在<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Apache</b>的httpd.Conf文件中，盘符、目录和文件的间隔要用斜杠“/”；在其他文件中如php.ini中则要用反斜杠“\”。 </p><!-- .entry-content --><img src ="http://www.cnitblog.com/benwhite/aggbug/20420.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2006-12-12 20:59 <a href="http://www.cnitblog.com/benwhite/archive/2006/12/12/20420.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《WINDOWS 游戏编程大师技巧 2nd Edition》学习笔记（1）</title><link>http://www.cnitblog.com/benwhite/archive/2006/10/31/18667.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Tue, 31 Oct 2006 09:13:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2006/10/31/18667.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/18667.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2006/10/31/18667.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/18667.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/18667.html</trackback:ping><description><![CDATA[
		<p>2006-10-31 周二<br /><font size="4"><strong><em>第1章 学海无涯</em></strong></font><br /><font style="BACKGROUND-COLOR: #ffffff" color="#008000">历史一瞥</font> dos游戏编程到底是怎样的呢？从最初的文字界面的小游戏到现在绚丽的3D游戏，硬件和软件的发展至关重要，微软的DrectX的开发更是提供了很好的工具，andre是很推崇microsoft的。<br /><font color="#008000">设计游戏</font> 点子并不难，关键是细节以及原先的想法最终有没有实现<br /><font color="#008000">游戏类型</font> 大致分类了一下，大约10类。我常常想还有没有完全或者至少游很大不同的新游戏类型呢？<br /><font color="#006400">集思广益</font> 多交流，并且新手的最初目标不要狂热，keep it simple！<br /><font color="#008000">设计文档&amp;情节图板</font> 总是要好好规划设计的，画画图更好的了解掌控开发<br /><font color="#008000">趣味性</font> 游戏应该使自己觉得有趣，关键是一些细节<br /><font color="#008000">游戏构成</font> 大致的框架－－主循环，等等<br /><font color="#008000">一些技巧</font> 一些andre的编程技巧，有很多需要自己亲身体验<br /><font color="#008000">使用工具</font> 编译器 2d艺术软件 声音处理 3D建模 midi 书本的光盘提供了很多哦<img height="19" src="http://www.cnitblog.com/Emoticons/teeth_smile.gif" width="19" border="0" /><br /><font color="#008000">例子</font>：FreakOut 一个乒乓球游戏 很简单 主要是计算反射等等<br /><br /><strong><em><font size="4">第2章 windows编程模型<br /></font></em></strong>“windows编程就像看牙医，虽然对自己有益处，可还是没人喜欢总是找牙医。对不对？”<br /><br /><strong>Windows的起源</strong> 这部分主要介绍了windows操作系统的发展情况，早期的版本效果很差，一直到3.X才渐入佳境， 到95推出后，一切都改变了。而98 ME XP都更加出色了。<br /><strong>多任务和多线程</strong> 复习一下操作系统，Round－robin轮询，执行不同的程序。<br /><strong>匈牙利符号表示法</strong> 一些规则，方便程序的易读性。慢慢习惯吧。<br /><strong>最简单的windows程序</strong> 一个弹出对话框的简易程序“there can be only one”解释了winmain的参数和信息框的使用<br /><font color="#000000"><strong>现实中的windows应用程序</strong></font> 1创建Windows类 2创建事件处理函数或Winproc 3注册windows类 4用windows类创建窗口 5建立主事件循环<br />                 以前这部分总是糊里糊涂的，现在总算是有较清晰的脉络了。<br /><br /></p>
<img src ="http://www.cnitblog.com/benwhite/aggbug/18667.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2006-10-31 17:13 <a href="http://www.cnitblog.com/benwhite/archive/2006/10/31/18667.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Begin the Game journey！！</title><link>http://www.cnitblog.com/benwhite/archive/2006/10/29/18591.html</link><dc:creator>BenWhite</dc:creator><author>BenWhite</author><pubDate>Sun, 29 Oct 2006 12:39:00 GMT</pubDate><guid>http://www.cnitblog.com/benwhite/archive/2006/10/29/18591.html</guid><wfw:comment>http://www.cnitblog.com/benwhite/comments/18591.html</wfw:comment><comments>http://www.cnitblog.com/benwhite/archive/2006/10/29/18591.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/benwhite/comments/commentRss/18591.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/benwhite/services/trackbacks/18591.html</trackback:ping><description><![CDATA[      <font face="Arial">Since long time ago,I had been so eager to make myself's game.But I always delay till now .I have touch some knowledge of game programming before,such like Windows program , game Enginer ,openGL etc without any systemic learning. Now I can ,after I read  the fist two chapters of book written by <strong><em>Andre Lamothe</em></strong> which we called </font><font face="Arial"><em>"<strong>Tricks of the Windows game programming gurus</strong>" (2nd Edition).<br /></em>      This is the best book I ever read at least in aspect of intrduction of windows programming .I get such a feeling that every black thing of windows program becomes totally clear.That's good start ,so I will go down along the direction till my game becomes true.</font><img src ="http://www.cnitblog.com/benwhite/aggbug/18591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/benwhite/" target="_blank">BenWhite</a> 2006-10-29 20:39 <a href="http://www.cnitblog.com/benwhite/archive/2006/10/29/18591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>