<?xml version="1.0" encoding="UTF-8"?>
<rss>
<channel>
<title>Rick 's BLOG</title>
<link>https://www.rickw.cn/</link>
<Description>Rick 's BLOG</Description>
<language>zh-cn</language>
<copyright>Copyright 2004-2025 Rick</copyright>
<webMaster>redcheek@gmail.net</webMaster>
<image>
	<title>Rick 's BLOG</title> 
	<url>https://www.rickw.cn/images/logos.gif</url> 
	<link>https://www.rickw.cn/</link> 
	<description>Rick 's BLOG</description> 
</image>
<item>
<link>https://www.rickw.cn/blogview/338</link>
<title><![CDATA[C++ 中 XML 库 TinyXML2 的基本使用方法]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2024-12-06 14:24:33</pubDate>
<guid>https://www.rickw.cn/blogview/338</guid>
	
<description><![CDATA[<h3>一、前言</h3><br />
TinyXML-2&nbsp;是一个简单，小型，高效的&nbsp;C&nbsp;++&nbsp;XML&nbsp;解析器，可以轻松集成到其他程序中。<br />
直接引用源文件的话只需要包含两个文件（h&nbsp;和&nbsp;cpp，此外还有个测试文件里面带有&nbsp;demo）。<br />
TinyXML-2&nbsp;解析&nbsp;XML&nbsp;文档，并以此为基础构建可读取，修改和保存的文档对象模型（DOM）。文档说，在解释&nbsp;XML&nbsp;时仅使用&nbsp;UTF-8&nbsp;编码，假定所有&nbsp;XML&nbsp;为&nbsp;UTF-8&nbsp;编码格式。<br />
该库还支持打印到文件或内存，使用&nbsp;XMLPrinter&nbsp;类。<br />
<br />
GitHub&nbsp;链接：https://github.com/leethomason/tinyxml2<br />
<br />
<h4>备用下载链接：<img src="/images/download.gif" align="absmiddle" /><a target="_blank" href="http://dl.rickw.cn/f/20272120-1433028805-d23fee">tinyxml2-10.0.0.zip</a>&nbsp;</h4><br />
<br />
（下载库项目后带有离线英文文档，可以浏览器在线翻译即可）<br />
<br />
<h3>二、基本使用方法</h3><br />
<br />
引入头文件：<br />
<div class="txt_main">#include&nbsp;"tinyxml2.h"<br />
&nbsp;<br />
//tinyxml2的类在tinyxml2命名空间<br />
using&nbsp;namespace&nbsp;tinyxml2;</div><br />
<br />
使用&nbsp;XMLDocument&nbsp;加载和保存&nbsp;XML&nbsp;文件：<br />
<div class="txt_main">//构造一个xml文档类<br />
XMLDocument&nbsp;doc;<br />
//读取文件<br />
//从磁盘加载XML文件。成功返回XML_SUCCESS（0），或者返回errorID。<br />
XMLError&nbsp;error&nbsp;=&nbsp;doc.LoadFile(xmlPath);<br />
//也可以解析字符串<br />
//XMLError&nbsp;tinyxml2::XMLDocument::Parse(const&nbsp;char&nbsp;*xml,size_t&nbsp;nBytes&nbsp;=&nbsp;static_cast&lt;size_t&gt;(-1));<br />
if&nbsp;(error&nbsp;!=&nbsp;XMLError::XML_SUCCESS)<br />
	return;<br />
//存储到文件，参数2&nbsp;compact紧凑默认false<br />
doc.SaveFile(xmlPath);</div><br />
<br />
可以借助&nbsp;XMLDocument&nbsp;生成节点（元素、属性、文本、注释等），也可以直接&nbsp;new&nbsp;生成对象，但还要使用&nbsp;Insert&nbsp;方法才能插入到结构中：<br />
<div class="txt_main">//元素<br />
XMLElement&nbsp;*&nbsp;tinyxml2::XMLDocument::NewElement&nbsp;(const&nbsp;char&nbsp;*name)<br />
//注释<br />
XMLComment&nbsp;*&nbsp;tinyxml2::XMLDocument::NewComment&nbsp;(const&nbsp;char&nbsp;*comment)<br />
//文本<br />
XMLText&nbsp;*&nbsp;tinyxml2::XMLDocument::NewText&nbsp;(const&nbsp;char&nbsp;*text)&nbsp;<br />
//XML文件头描述<br />
XMLDeclaration&nbsp;*&nbsp;tinyxml2::XMLDocument::NewDeclaration&nbsp;(const&nbsp;char&nbsp;*text=0)<br />
//未知类型<br />
XMLUnknown&nbsp;*&nbsp;tinyxml2::XMLDocument::NewUnknown&nbsp;(const&nbsp;char&nbsp;*text)<br />
&nbsp;<br />
//插入到末尾<br />
XMLNode&nbsp;*&nbsp;tinyxml2::XMLNode::InsertEndChild&nbsp;(XMLNode&nbsp;*addThis)<br />
//插入到开头<br />
XMLNode&nbsp;*&nbsp;tinyxml2::XMLNode::InsertFirstChild&nbsp;(XMLNode&nbsp;*addThis)<br />
//插入到节点的下一个位置<br />
XMLNode&nbsp;*&nbsp;tinyxml2::XMLNode::InsertAfterChild&nbsp;(XMLNode&nbsp;*afterThis,&nbsp;XMLNode&nbsp;*addThis)</div><br />
<br />
删除子节点：<br />
<div class="txt_main">//是否不包含子节点<br />
bool&nbsp;tinyxml2::XMLNode::NoChildren&nbsp;()&nbsp;const<br />
//第一个子节点<br />
const&nbsp;XMLNode&nbsp;*&nbsp;tinyxml2::XMLNode::FirstChild&nbsp;()&nbsp;const<br />
//第一个子元素&nbsp;<br />
const&nbsp;XMLElement&nbsp;*&nbsp;tinyxml2::XMLNode::FirstChildElement&nbsp;(const&nbsp;char&nbsp;*name=0)&nbsp;const<br />
//最后一个子节点<br />
const&nbsp;XMLNode&nbsp;*&nbsp;tinyxml2::XMLNode::LastChild&nbsp;()&nbsp;const<br />
//最后一个子元素<br />
const&nbsp;XMLElement&nbsp;*&nbsp;tinyxml2::XMLNode::LastChildElement&nbsp;(const&nbsp;char&nbsp;*name=0)&nbsp;const<br />
//上一个兄弟节点&nbsp;<br />
const&nbsp;XMLNode&nbsp;*&nbsp;tinyxml2::XMLNode::PreviousSibling&nbsp;()&nbsp;const<br />
//上一个兄弟元素&nbsp;<br />
const&nbsp;XMLElement&nbsp;*&nbsp;tinyxml2::XMLNode::PreviousSiblingElement&nbsp;(const&nbsp;char&nbsp;*name=0)&nbsp;const<br />
//下一个兄弟节点<br />
const&nbsp;XMLNode&nbsp;*&nbsp;tinyxml2::XMLNode::NextSibling&nbsp;()&nbsp;const<br />
//下一个兄弟元素<br />
const&nbsp;XMLElement&nbsp;*&nbsp;tinyxml2::XMLNode::NextSiblingElement&nbsp;(const&nbsp;char&nbsp;*name=0)&nbsp;const</div><br />
<br />
如果要遍历整个文档，可从&nbsp;XMLDocument&nbsp;开始遍历，XXXChild&nbsp;+&nbsp;XXXSibling&nbsp;遍历所有的子节点和兄弟节点。<br />
<br />
<h3>三、简单完整示例代码</h3><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_AhngErKFyjbE')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_AhngErKFyjbE);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_AhngErKFyjbE" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><code><span style="color: #000000"><br />
<span style="color: #FF8000">#include&nbsp;&lt;iostream&gt;<br />#include&nbsp;&lt;string&gt;<br />&nbsp;<br />#include&nbsp;"tinyxml2.h"<br />&nbsp;<br />//tinyxml2的类在tinyxml2命名空间<br /></span><span style="color: #0000BB">using&nbsp;</span><span style="color: #007700">namespace&nbsp;</span><span style="color: #0000BB">tinyxml2</span><span style="color: #007700">;<br />&nbsp;<br /></span><span style="color: #FF8000">//测试生成xml<br /></span><span style="color: #0000BB">void&nbsp;create_xml</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//测试解析xml<br /></span><span style="color: #0000BB">void&nbsp;parse_xml</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//遍历xml&nbsp;node<br /></span><span style="color: #0000BB">void&nbsp;traversal_node</span><span style="color: #007700">(</span><span style="color: #0000BB">XMLNode</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">node</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//遍历xml&nbsp;element<br /></span><span style="color: #0000BB">void&nbsp;traversal_element</span><span style="color: #007700">(</span><span style="color: #0000BB">XMLNode</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">node</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">int&nbsp;level</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//生成预定格式xml<br /></span><span style="color: #0000BB">void&nbsp;create_xml2</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//解析预定义格式xml<br /></span><span style="color: #0000BB">void&nbsp;parse_xml2</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">int&nbsp;main</span><span style="color: #007700">()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">path&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"./test.xml"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">create_xml</span><span style="color: #007700">(</span><span style="color: #0000BB">path</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">parse_xml</span><span style="color: #007700">(</span><span style="color: #0000BB">path</span><span style="color: #007700">);<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">path2&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"./test2.xml"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">create_xml2</span><span style="color: #007700">(</span><span style="color: #0000BB">path2</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">parse_xml2</span><span style="color: #007700">(</span><span style="color: #0000BB">path2</span><span style="color: #007700">);<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">system</span><span style="color: #007700">(</span><span style="color: #DD0000">"pause"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">void&nbsp;create_xml</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"\ncreate_xml:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">xmlPath&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】构造一个xml文档类<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLDocument&nbsp;doc</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】操作文档相关接口<br />&nbsp;&nbsp;&nbsp;&nbsp;//创建与此文档关联的新声明。对象的内存由文档管理。<br />&nbsp;&nbsp;&nbsp;&nbsp;//如果'text'参数为null，则使用标准声明:<br />&nbsp;&nbsp;&nbsp;&nbsp;//&lt;?xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"?&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLDeclaration</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">declaration&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">NewDeclaration</span><span style="color: #007700">();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//创建与此文档关联的新元素。元素的内存由文档管理。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">element&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">NewElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementA"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//创建与此文档关联的新注释。注释的内存由文档管理。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLComment</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">comment&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">NewComment</span><span style="color: #007700">(</span><span style="color: #DD0000">"My&nbsp;TinyXml2&nbsp;Test...&nbsp;..."</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//创建与此文档关联的新文本。文本的存储由文档管理。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLText</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">text&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">NewText</span><span style="color: #007700">(</span><span style="color: #DD0000">"Some&nbsp;Test"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//创建与此文档关联的新的未知节点。对象的内存由文档管理。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLUnknown</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">unknown&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">NewUnknown</span><span style="color: #007700">(</span><span style="color: #DD0000">"Unknown"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】创建了节点还要插入文档中<br />&nbsp;&nbsp;&nbsp;&nbsp;//添加一个子节点作为最后一个（右）子节点。如果子节点已经是文档的一部分，则将其从其旧位置移至新位置。<br />&nbsp;&nbsp;&nbsp;&nbsp;//XMLNode*&nbsp;tinyxml2::XMLNode::InsertEndChild(XMLNode&nbsp;*&nbsp;addThis);<br />&nbsp;&nbsp;&nbsp;&nbsp;//添加一个子节点作为第一个（左）子节点。如果子节点已经是文档的一部分，则将其从其旧位置移至新位置。<br />&nbsp;&nbsp;&nbsp;&nbsp;//XMLNode*&nbsp;tinyxml2::XMLNode::InsertFirstChild(XMLNode*&nbsp;addThis);<br />&nbsp;&nbsp;&nbsp;&nbsp;//在指定的子节点之后添加一个节点。如果子节点已经是文档的一部分，则将其从其旧位置移至新位置。<br />&nbsp;&nbsp;&nbsp;&nbsp;//XMLNode*&nbsp;tinyxml2::XMLNode::InsertAfterChild(XMLNode&nbsp;*&nbsp;afterThis,&nbsp;XMLNode&nbsp;*&nbsp;addThis);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">InsertFirstChild</span><span style="color: #007700">(</span><span style="color: #0000BB">declaration</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">InsertAfterChild</span><span style="color: #007700">(</span><span style="color: #0000BB">declaration</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">element</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">InsertEndChild</span><span style="color: #007700">(</span><span style="color: #0000BB">comment</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">InsertEndChild</span><span style="color: #007700">(</span><span style="color: #0000BB">text</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">InsertEndChild</span><span style="color: #007700">(</span><span style="color: #0000BB">unknown</span><span style="color: #007700">);<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】操作节点相关接口<br />&nbsp;&nbsp;&nbsp;&nbsp;//将命名属性设置为对应类型的value<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetAttribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Level"</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"A"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetAttribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Value"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">1992</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//设置文本<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementA&nbsp;text"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//注释<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewComment</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementA&nbsp;comment"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//添加子节点，接口已经带insert功能了<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">sub_element&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementB"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">sub_element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetAttribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Level"</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"B"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">sub_element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementB&nbsp;text"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">sub_element</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewComment</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementB&nbsp;comment"</span><span style="color: #007700">);<br />&nbsp;<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】存储到文件，参数2&nbsp;compact紧凑默认false<br />&nbsp;&nbsp;&nbsp;&nbsp;//结构写的不规范，感觉应该拿一个根节点把那些注释，文本包起来<br />&nbsp;&nbsp;&nbsp;&nbsp;//不然解析的时候没法访问啊<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">SaveFile</span><span style="color: #007700">(</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br />}<br /><br /></span><span style="color: #0000BB">void&nbsp;parse_xml</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"\nparse_xml:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">xmlPath&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】构造一个xml文档类<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLDocument&nbsp;doc</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】读取文件<br />&nbsp;&nbsp;&nbsp;&nbsp;//从磁盘加载XML文件。成功返回XML_SUCCESS（0），或者返回errorID。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLError&nbsp;error&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">LoadFile</span><span style="color: #007700">(</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//也可以解析字符串<br />&nbsp;&nbsp;&nbsp;&nbsp;//从字符串解析XML文件。成功返回XML_SUCCESS（0），或者返回errorID。<br />&nbsp;&nbsp;&nbsp;&nbsp;//XMLError&nbsp;tinyxml2::XMLDocument::Parse(const&nbsp;char&nbsp;*xml,size_t&nbsp;nBytes&nbsp;=&nbsp;static_cast&lt;size_t&gt;(-1));<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">if&nbsp;(</span><span style="color: #0000BB">error&nbsp;</span><span style="color: #007700">!=&nbsp;</span><span style="color: #0000BB">XMLError</span><span style="color: #007700">::</span><span style="color: #0000BB">XML_SUCCESS</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//注意，实际解析时返回的指针记得判空，不然遇到解析失败异常就遭了<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;//【】解析根元素<br />&nbsp;&nbsp;&nbsp;&nbsp;//返回DOM的根元素。等效于FirstChildElement。要获取第一个节点，请使用FirstChild。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">root&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">RootElement</span><span style="color: #007700">();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"RootElement&nbsp;name:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">root</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Name</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//获取第一个子元素，或者选择具有指定名称的第一个子元素。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">first&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">FirstChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementA"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//给定一个属性名称，Attribute返回该名称的属性的值；如果不存在，则返回null。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"FirstChildElement&nbsp;Attr&nbsp;Level:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">first</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Attribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Level"</span><span style="color: #007700">)&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"FirstChildElement&nbsp;Attr&nbsp;Value:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">first</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Attribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Value"</span><span style="color: #007700">)&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//如果'this'的第一个Child是XMLText，则GetText返回Text节点的字符串，否则返回null。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"FirstChildElement&nbsp;Text:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">first</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">GetText</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】解析子元素<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">sub&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">root</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FirstChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"ElementB"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"SubElement&nbsp;Attr&nbsp;Level:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">sub</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Attribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Level"</span><span style="color: #007700">)&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"SubElement&nbsp;Text:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">sub</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">GetText</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】<br />&nbsp;&nbsp;&nbsp;&nbsp;//可使用FirstChild+NextSibling遍历子节点<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"\ntraversal_xml:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">traversal_node</span><span style="color: #007700">(&amp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//或者FirstChildElement+NextSiblingElement遍历子元素<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"\ntraversal_element:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">traversal_element</span><span style="color: #007700">(&amp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />}<br />&nbsp;<br /></span><span style="color: #0000BB">void&nbsp;traversal_node</span><span style="color: #007700">(</span><span style="color: #0000BB">XMLNode</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">node</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!</span><span style="color: #0000BB">node</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(</span><span style="color: #0000BB">XMLNode</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">current&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">node</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FirstChild</span><span style="color: #007700">();&nbsp;</span><span style="color: #0000BB">current&nbsp;</span><span style="color: #007700">!=&nbsp;</span><span style="color: #0000BB">nullptr</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">current&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">current</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">NextSibling</span><span style="color: #007700">())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLNode</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">temp&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">current</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Value</span><span style="color: #007700">()&nbsp;!=&nbsp;</span><span style="color: #0000BB">nullptr</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Value</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">NoChildren</span><span style="color: #007700">())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">traversal_node</span><span style="color: #007700">(</span><span style="color: #0000BB">temp</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000BB">void&nbsp;traversal_element</span><span style="color: #007700">(</span><span style="color: #0000BB">XMLNode</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">node</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">int&nbsp;level</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!</span><span style="color: #0000BB">node</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">current&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">node</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FirstChildElement</span><span style="color: #007700">();&nbsp;</span><span style="color: #0000BB">current&nbsp;</span><span style="color: #007700">!=&nbsp;</span><span style="color: #0000BB">nullptr</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">current&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">current</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">NextSiblingElement</span><span style="color: #007700">())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">temp&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">current</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//这里我使用点号来表示层级缩进<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">string</span><span style="color: #007700">(</span><span style="color: #0000BB">level&nbsp;</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">5</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">'.'</span><span style="color: #007700">)&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Name</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">GetText</span><span style="color: #007700">()&nbsp;!=&nbsp;</span><span style="color: #0000BB">nullptr</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">string</span><span style="color: #007700">(</span><span style="color: #0000BB">level&nbsp;</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">5</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">'.'</span><span style="color: #007700">)&nbsp;&lt;&lt;&nbsp;</span><span style="color: #DD0000">"&gt;&nbsp;Text"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">":"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">GetText</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;</span><span style="color: #0000BB">XMLAttribute</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">attr&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FirstAttribute</span><span style="color: #007700">();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #0000BB">attr&nbsp;</span><span style="color: #007700">!=&nbsp;</span><span style="color: #0000BB">nullptr</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">string</span><span style="color: #007700">(</span><span style="color: #0000BB">level&nbsp;</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">5</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">'.'</span><span style="color: #007700">)&nbsp;&lt;&lt;&nbsp;</span><span style="color: #DD0000">"&gt;&nbsp;Attr"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">":"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">attr</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Value</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #0000BB">temp</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FirstChildElement</span><span style="color: #007700">()&nbsp;!=&nbsp;</span><span style="color: #0000BB">nullptr</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">traversal_element</span><span style="color: #007700">(</span><span style="color: #0000BB">temp</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">level&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000BB">void&nbsp;create_xml2</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"\ncreate_xml2:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">xmlPath&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】构造一个xml文档类<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLDocument&nbsp;doc</span><span style="color: #007700">;<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】构建我们的xml数据结构<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLDeclaration</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">declaration&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">NewDeclaration</span><span style="color: #007700">();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">InsertFirstChild</span><span style="color: #007700">(</span><span style="color: #0000BB">declaration</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//创建与此文档关联的新元素。元素的内存由文档管理。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">root&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">NewElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Root"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">InsertEndChild</span><span style="color: #007700">(</span><span style="color: #0000BB">root</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//子节点<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">group_a&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">root</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"GroupA"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">group_a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetAttribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Type"</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"A"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">a_1&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">group_a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Name"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">a_1</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"中文"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">a_1_sub&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">a_1</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Content"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">a_1_sub</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"111111"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">a_2&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">group_a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Name"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">a_2</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"English"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">a_2_sub&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">a_2</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Content"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">a_2_sub</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"222222"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">a_3&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">group_a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Name"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">a_3</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"123"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">a_3_sub&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">a_3</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Content"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">a_3_sub</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetText</span><span style="color: #007700">(</span><span style="color: #DD0000">"333333"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">group_b&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">root</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"GroupB"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">group_b</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetAttribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Type"</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"B"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">group_c&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">root</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">InsertNewChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"GroupC"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">group_c</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">SetAttribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Type"</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"C"</span><span style="color: #007700">);<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】存储到文件，参数2&nbsp;compact紧凑默认false<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">SaveFile</span><span style="color: #007700">(</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br />}<br /><br /></span><span style="color: #0000BB">void&nbsp;parse_xml2</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"\nparse_xml2:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">xmlPath&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】构造一个xml文档类<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLDocument&nbsp;doc</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】读取文件<br />&nbsp;&nbsp;&nbsp;&nbsp;//从磁盘加载XML文件。成功返回XML_SUCCESS（0），或者返回errorID。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLError&nbsp;error&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">LoadFile</span><span style="color: #007700">(</span><span style="color: #0000BB">xmlPath</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//也可以解析字符串<br />&nbsp;&nbsp;&nbsp;&nbsp;//从字符串解析XML文件。成功返回XML_SUCCESS（0），或者返回errorID。<br />&nbsp;&nbsp;&nbsp;&nbsp;//XMLError&nbsp;tinyxml2::XMLDocument::Parse(const&nbsp;char&nbsp;*xml,size_t&nbsp;nBytes&nbsp;=&nbsp;static_cast&lt;size_t&gt;(-1));<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">if&nbsp;(</span><span style="color: #0000BB">error&nbsp;</span><span style="color: #007700">!=&nbsp;</span><span style="color: #0000BB">XMLError</span><span style="color: #007700">::</span><span style="color: #0000BB">XML_SUCCESS</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//注意，实际解析时返回的指针记得判空，不然遇到解析失败异常就遭了<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;//【】解析根节点<br />&nbsp;&nbsp;&nbsp;&nbsp;//返回DOM的根元素。等效于FirstChildElement。要获取第一个节点，请使用FirstChild。<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">root&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">.</span><span style="color: #0000BB">RootElement</span><span style="color: #007700">();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】查找<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">find_ele&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">root</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FirstChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"GroupA"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #0000BB">find_ele</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">find_ele</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Name</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;</span><span style="color: #0000BB">XMLAttribute</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">attr&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">find_ele</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FindAttribute</span><span style="color: #007700">(</span><span style="color: #DD0000">"Type"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #0000BB">attr</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">attr</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Name</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #DD0000">":"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">attr</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">Value</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">XMLElement</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">find_sub&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">find_ele</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">FirstChildElement</span><span style="color: #007700">(</span><span style="color: #DD0000">"Name"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #0000BB">find_sub&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;</span><span style="color: #0000BB">find_sub</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">GetText</span><span style="color: #007700">())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">find_sub</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">GetText</span><span style="color: #007700">()&nbsp;&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//【】遍历<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">cout&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #DD0000">"\ntraversal_element:"&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">std</span><span style="color: #007700">::</span><span style="color: #0000BB">endl</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">traversal_element</span><span style="color: #007700">(&amp;</span><span style="color: #0000BB">doc</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />}&nbsp;</span><br />
</span><br />
</code></div>]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/314</link>
<title><![CDATA[vc6、vc7、vc8、vc9、vc10、vc11、vc12、vc14、vc15各代表Visual Studio C++什么版本]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2023-12-20 13:55:40</pubDate>
<guid>https://www.rickw.cn/blogview/314</guid>
	
<description><![CDATA[<strong>单来说vs发布版本与vc版本对应关系如下所示：</strong><br />
<br />
<ul><li>Visual&nbsp;Studio&nbsp;6&nbsp;：&nbsp;vc6&nbsp;<li>Visual&nbsp;Studio&nbsp;2003&nbsp;：&nbsp;vc7&nbsp;<li>Visual&nbsp;Studio&nbsp;2005&nbsp;：&nbsp;vc8&nbsp;<li>Visual&nbsp;Studio&nbsp;2008&nbsp;：&nbsp;vc9<br />
<li>Visual&nbsp;Studio&nbsp;2010&nbsp;：&nbsp;vc10&nbsp;<li>Visual&nbsp;Studio&nbsp;2012&nbsp;：&nbsp;vc11&nbsp;<li>Visual&nbsp;Studio&nbsp;2013&nbsp;：&nbsp;vc12<br />
<li>Visual&nbsp;Studio&nbsp;2015&nbsp;：&nbsp;vc14&nbsp;<li>Visual&nbsp;Studio&nbsp;2017&nbsp;：&nbsp;vc15&nbsp;</ul></ol>]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/298</link>
<title><![CDATA[向现有的MFC项目添加ATL支持。]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2023-12-08 23:20:20</pubDate>
<guid>https://www.rickw.cn/blogview/298</guid>
	
<description><![CDATA[如果在现有的MFC项目中实现了依赖ATL基础库的Com对象时，直接运行会出现异常：<br />
CComCritSecLock&lt;CComCriticalSection&gt;&nbsp;lock(_pAtlModule-&gt;m_csStaticDataInitAndTypeInfo,&nbsp;false);<br />
<br />
像上面的代码在atlcom.h中，_pAtlModule&nbsp;的值为空，没有初始化。<br />
<br />
网上说可以通过添加类向导，然后选择&nbsp;添加ATL支持到现有的MFC项目。<br />
<br />
实际测试，发现老项目在添加时会失败。只有新建的MFC项目可以添加成功。<br />
<br />
然后，添加的结果也不满意，多了一些不需要的东西。<br />
1，添加了idl文件，会在编译时生成tlb库。<br />
2，在资源中添加了tlb库，会将tlb库链接到程序资源中。<br />
3，添加了rgs文件（注册表项目）。<br />
4，会在调用com对象时进行自注册操作（将rgs导入注册表）。<br />
<br />
上面这些都是我不想要的，我只是想干干净净的，让我实现的com对象可以正常调用传递参数就行了。<br />
不需要在系统中注册com组件。<br />
<br />
对过对比分析新的mfc项目添加atl支持后的代码，发现添加支持很简单。<br />
在现有的cpp文件中添加如下代码即可。<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_B7WyOlSgS4xQ')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_B7WyOlSgS4xQ);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_B7WyOlSgS4xQ" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><code><span style="color: #000000"><br />
<span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">CMFCApplication1Module&nbsp;</span><span style="color: #007700">:public&nbsp;</span><span style="color: #0000BB">ATL</span><span style="color: #007700">::</span><span style="color: #0000BB">CAtlMfcModule<br /></span><span style="color: #007700">{<br />};<br /><br /></span><span style="color: #0000BB">CMFCApplication1Module&nbsp;_AtlModule</span><span style="color: #007700">;<br />&nbsp;</span><br />
</span><br />
</code></div><br />
<br />
就像上面这样，定义一个atl的app类。<br />
再实例一个对象即可。<br />
]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/297</link>
<title><![CDATA[VS 2005打开类视图]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2023-12-07 21:15:21</pubDate>
<guid>https://www.rickw.cn/blogview/297</guid>
	
<description><![CDATA[比较奇怪这边的&nbsp;VS2005&nbsp;视图&nbsp;菜单下面没有发现&nbsp;类视图&nbsp;项目。<br />
打开的工程里面不显示&nbsp;类视图，不知道是不是环境设置的问题。<br />
<br />
还好快捷键有效&nbsp;ctrl+shift+C<br />
可以通过快捷键打开类视图。<br />
]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/293</link>
<title><![CDATA[C++中实现字符串编码转换GBK转UTF8]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2023-12-05 23:52:41</pubDate>
<guid>https://www.rickw.cn/blogview/293</guid>
	
<description><![CDATA[在C++中实现GBK和Utf8字符串的互转。<br />
先定义字符串编码的codepage值。<br />
#define&nbsp;CP_GBK&nbsp;936<br />
#define&nbsp;CP_UTF8&nbsp;65001<br />
<br />
<strong>Utf8字符串转GBK</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_8YFW53rFxMxg')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_8YFW53rFxMxg);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_8YFW53rFxMxg" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><code><span style="color: #000000"><br />
<span style="color: #0000BB"><br />void&nbsp;Utf8Gbk</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">CString</span><span style="color: #007700">&amp;&nbsp;</span><span style="color: #0000BB">szUtf8</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">CString</span><span style="color: #007700">&amp;&nbsp;</span><span style="color: #0000BB">szGbk</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">int&nbsp;buffLen&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">int&nbsp;wlen&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">szUtf8</span><span style="color: #007700">.</span><span style="color: #0000BB">GetLength</span><span style="color: #007700">();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">WCHAR</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">wbuff&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">WCHAR</span><span style="color: #007700">[</span><span style="color: #0000BB">wlen</span><span style="color: #007700">+</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">MultiByteToWideChar</span><span style="color: #007700">(</span><span style="color: #0000BB">CP_UTF8</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">szUtf8</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wlen</span><span style="color: #007700">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">buffLen&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">WideCharToMultiByte</span><span style="color: #007700">(</span><span style="color: #0000BB">CP_GBK</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">NULL</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">gbk&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">[</span><span style="color: #0000BB">buffLen</span><span style="color: #007700">+</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">WideCharToMultiByte</span><span style="color: #007700">(</span><span style="color: #0000BB">CP_GBK</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;(</span><span style="color: #0000BB">LPSTR</span><span style="color: #007700">)</span><span style="color: #0000BB">gbk</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">buffLen</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">delete</span><span style="color: #007700">[]</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">szGbk&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">gbk</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">delete</span><span style="color: #007700">[]</span><span style="color: #0000BB">gbk</span><span style="color: #007700">;&nbsp;&nbsp;&nbsp;&nbsp;<br />}&nbsp;</span><br />
</span><br />
</code></div><br />
<br />
<strong>GBK字符串转Utf8</strong><script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_D9Usz8acNFYg')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_D9Usz8acNFYg);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_D9Usz8acNFYg" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><code><span style="color: #000000"><br />
<span style="color: #0000BB"><br />void&nbsp;GbkUtf8</span><span style="color: #007700">(const&nbsp;</span><span style="color: #0000BB">CString</span><span style="color: #007700">&amp;&nbsp;</span><span style="color: #0000BB">szGbk</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">CString</span><span style="color: #007700">&amp;&nbsp;</span><span style="color: #0000BB">szUtf8</span><span style="color: #007700">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">int&nbsp;buffLen&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">int&nbsp;wlen&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">szGbk</span><span style="color: #007700">.</span><span style="color: #0000BB">GetLength</span><span style="color: #007700">()*</span><span style="color: #0000BB">3</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">WCHAR</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">wbuff&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">WCHAR</span><span style="color: #007700">[</span><span style="color: #0000BB">wlen</span><span style="color: #007700">+</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">MultiByteToWideChar</span><span style="color: #007700">(</span><span style="color: #0000BB">CP_GBK</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">szGbk</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wlen</span><span style="color: #007700">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">buffLen&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">WideCharToMultiByte</span><span style="color: #007700">(</span><span style="color: #0000BB">CP_UTF8</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">NULL</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">utf8&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">char</span><span style="color: #007700">[</span><span style="color: #0000BB">buffLen</span><span style="color: #007700">+</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">WideCharToMultiByte</span><span style="color: #007700">(</span><span style="color: #0000BB">CP_UTF8</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;(</span><span style="color: #0000BB">LPSTR</span><span style="color: #007700">)</span><span style="color: #0000BB">utf8</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">buffLen</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">delete</span><span style="color: #007700">[]</span><span style="color: #0000BB">wbuff</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">szUtf8&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">utf8</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">delete</span><span style="color: #007700">[]</span><span style="color: #0000BB">utf8</span><span style="color: #007700">;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />}&nbsp;</span><br />
</span><br />
</code></div>]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/190</link>
<title><![CDATA[权限提升代码]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2007-08-22 00:04:00</pubDate>
<guid>https://www.rickw.cn/blogview/190</guid>
	
<description><![CDATA[提升当前的进程权限<br />
<br />
<br />
void AdjustPrivilege(int pid, BOOL bEnable)<br />
{<br />
    HANDLE    hProcess;<br />
  HANDLE    hToken=0;<br />
    TOKEN_PRIVILEGES tkp;<br />
  tkp.PrivilegeCount = 1;  <br />
  tkp.Privileges[0].Attributes = 0;<br />
  if (bEnable)<br />
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;<br />
  if (LookupPrivilegeValue(NULL, "SeDebugPrivilege", &amp;tkp.Privileges[0].Luid))<br />
  {<br />
    if (hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))<br />
    {<br />
      if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &amp;hToken))<br />
      {<br />
        if (AdjustTokenPrivileges(hToken, FALSE, &amp;tkp, 0, NULL, NULL))<br />
        {<br />
          CloseHandle(hToken);<br />
        }<br />
      }<br />
      CloseHandle(hProcess);<br />
    }<br />
  }<br />
}]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/189</link>
<title><![CDATA[防止注入的代码]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2007-08-22 00:03:00</pubDate>
<guid>https://www.rickw.cn/blogview/189</guid>
	
<description><![CDATA[#define PROTECTED_DACL_SECURITY_INFORMATION (0x80000000L)<br />
<br />
BOOL Lock_CurrentProcess()<br />
{<br />
  HANDLE hProcess = ::GetCurrentProcess();<br />
  SID_IDENTIFIER_AUTHORITY sia = SECURITY_WORLD_SID_AUTHORITY;<br />
  PSID pSid;<br />
  BOOL bSus = FALSE;<br />
  bSus = ::AllocateAndInitializeSid(&amp;sia,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&amp;pSid);<br />
  if(!bSus) goto Cleanup;<br />
  HANDLE hToken;<br />
  bSus = ::OpenProcessToken(hProcess,TOKEN_QUERY,&amp;hToken);<br />
  if(!bSus) goto Cleanup;<br />
  DWORD dwReturnLength;<br />
  ::GetTokenInformation(hToken,TokenUser,NULL,NULL,&amp;dwReturnLength);<br />
  if(dwReturnLength &gt; 0x400) goto Cleanup;<br />
  LPVOID TokenInformation;<br />
  TokenInformation = ::LocalAlloc(LPTR,0x400);//这里就引用SDK的函数不引用CRT的了<br />
  DWORD dw;<br />
  bSus = ::GetTokenInformation(hToken,TokenUser,TokenInformation,0x400,&amp;dw);<br />
  if(!bSus) goto Cleanup;<br />
  PTOKEN_USER pTokenUser = (PTOKEN_USER)TokenInformation;<br />
  BYTE Buf[0x200];<br />
  PACL pAcl = (PACL)&amp;Buf;<br />
  bSus = ::InitializeAcl(pAcl,1024,ACL_REVISION);<br />
  if(!bSus) goto Cleanup;<br />
  bSus = ::AddAccessDeniedAce(pAcl,ACL_REVISION,0x000000FA,pSid);<br />
  if(!bSus) goto Cleanup;<br />
  bSus = ::AddAccessAllowedAce(pAcl,ACL_REVISION,0x00100701,pTokenUser-&gt;User.Sid);<br />
  if(!bSus) goto Cleanup;<br />
  if(::SetSecurityInfo(hProcess,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,NULL,NULL,pAcl,NULL) == 0)<br />
    bSus = TRUE;<br />
Cleanup:<br />
  if(hProcess != NULL)<br />
    ::CloseHandle(hProcess);<br />
  if(pSid != NULL)<br />
    ::FreeSid(pSid);<br />
  return bSus;<br />
}<br />
<br />
这段代码就可以锁住其他进程打开本进程,当然也就防止了注入,和读写内存.<br />
<br />
可以更绝点Denied ALL ACCESS(0xFFFFFFFF)就连结束都不可能了<br />
<br />
::AllocateAndInitializeSid 可以换成 :: InitializeSid .因为我们并不需要初始化子Sid.<br />
另外.<br />
  bSus = ::AddAccessDeniedAce(pAcl,ACL_REVISION,0x000000FA,pSid);<br />
  if(!bSus) goto Cleanup;<br />
  bSus = ::AddAccessAllowedAce(pAcl,ACL_REVISION,0x00100701,pTokenUser-&gt;User.Sid);<br />
实际上只需要下面的一句,或者干脆把它去掉,因为如果不添加Ace默认就是没有权限.既然这样上面的那句话AllocateAndInitializeSid 也可以省掉,也似乎有些多余]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/148</link>
<title><![CDATA[C++ 中 naked 函数调用]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2006-10-28 20:02:00</pubDate>
<guid>https://www.rickw.cn/blogview/148</guid>
	
<description><![CDATA[正常的情况下，我们写一个&nbsp;C/C++&nbsp;函数，即使是一个空函数，编译器也为我们做了不少的工作，生成了一些“必要”的代码。<br />
请看下面的函数&nbsp;(为了说明问题随便写的):<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_AG0VBd5psACD')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_AG0VBd5psACD);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_AG0VBd5psACD" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><code><span style="color: #000000"><br />
<span style="color: #0000BB"><br />int&nbsp;Test</span><span style="color: #007700">()<br />&nbsp;{&nbsp;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;int&nbsp;iReturn</span><span style="color: #007700">;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;char&nbsp;szTemp</span><span style="color: #007700">[</span><span style="color: #0000BB">33</span><span style="color: #007700">];<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;<br />&nbsp; &nbsp; &nbsp;szTemp</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]&nbsp;=&nbsp;</span><span style="color: #DD0000">'A'</span><span style="color: #007700">;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;szTemp</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]&nbsp;=&nbsp;</span><span style="color: #DD0000">''</span><span style="color: #007700">;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;iReturn&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">MessageBox</span><span style="color: #007700">(</span><span style="color: #0000BB">NULL</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">szTemp</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">szTemp</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">MB_OK</span><span style="color: #007700">);<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;MessageBeep</span><span style="color: #007700">(</span><span style="color: #0000BB">iReturn</span><span style="color: #007700">);<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">return&nbsp;</span><span style="color: #0000BB">iReturn</span><span style="color: #007700">;<br />&nbsp;</span><span style="color: #0000BB"> </span><span style="color: #007700">}<br />&nbsp;</span><br />
</span><br />
</code></div><br />
<br />
下面是用&nbsp;VC6&nbsp;在&nbsp;Release&nbsp;方式下编译后的的反汇编代码:<br />
<br />
<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_lG6mZNeDlR0W')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_lG6mZNeDlR0W);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_lG6mZNeDlR0W" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><code><span style="color: #000000"><br />
<span style="color: #0000BB"><br />00401000&nbsp; &nbsp;sub&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;esp</span><span style="color: #007700">,</span><span style="color: #0000BB">24h&nbsp; &nbsp; &nbsp;</span><span style="color: #FF8000">//&nbsp;增加堆栈空间存放局部变量&nbsp;(24H&nbsp;=&nbsp;36D，4&nbsp;字节对齐，注意这里没有为&nbsp;iReturn&nbsp;分配空间)<br />&nbsp;</span><span style="color: #0000BB">00401003&nbsp; &nbsp;push&nbsp; &nbsp; &nbsp; &nbsp; esi&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #FF8000">//&nbsp;保存要使用的重要寄存器<br />&nbsp;</span><span style="color: #0000BB">00401004&nbsp; &nbsp;lea&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;eax</span><span style="color: #007700">,[</span><span style="color: #0000BB">esp</span><span style="color: #007700">+</span><span style="color: #0000BB">4</span><span style="color: #007700">]&nbsp;</span><span style="color: #FF8000">//&nbsp;下面是传递&nbsp;MessageBox()&nbsp;要使用的参数<br />&nbsp;</span><span style="color: #0000BB">00401008&nbsp; &nbsp;push&nbsp; &nbsp; &nbsp; &nbsp; 0<br />&nbsp;0040100A&nbsp; &nbsp;lea&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ecx</span><span style="color: #007700">,[</span><span style="color: #0000BB">esp</span><span style="color: #007700">+</span><span style="color: #0000BB">8</span><span style="color: #007700">]&nbsp;</span><span style="color: #FF8000">//&nbsp;编译器愚蠢，根本不用&nbsp;ECX，两个都是&nbsp;szTemp，两次&nbsp;PUSH&nbsp;EAX&nbsp;不得了<br />&nbsp;</span><span style="color: #0000BB">0040100E&nbsp; &nbsp;push&nbsp; &nbsp; &nbsp; &nbsp; eax<br />&nbsp;0040100F&nbsp; &nbsp;push&nbsp; &nbsp; &nbsp; &nbsp; ecx<br />&nbsp;00401010&nbsp; &nbsp;push&nbsp; &nbsp; &nbsp; &nbsp; 0<br />&nbsp;00401012&nbsp; &nbsp;mov&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;byte&nbsp;ptr&nbsp;</span><span style="color: #007700">[</span><span style="color: #0000BB">esp</span><span style="color: #007700">+</span><span style="color: #0000BB">14h</span><span style="color: #007700">],</span><span style="color: #0000BB">41h<br />&nbsp;00401017&nbsp; &nbsp;mov&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;byte&nbsp;ptr&nbsp;</span><span style="color: #007700">[</span><span style="color: #0000BB">esp</span><span style="color: #007700">+</span><span style="color: #0000BB">15h</span><span style="color: #007700">],</span><span style="color: #0000BB">0<br />&nbsp;0040101C&nbsp; &nbsp;call&nbsp; &nbsp; &nbsp; &nbsp; dword&nbsp;ptr&nbsp;ds</span><span style="color: #007700">:[</span><span style="color: #0000BB">40509Ch</span><span style="color: #007700">]&nbsp;</span><span style="color: #FF8000">//&nbsp;调用&nbsp;MessageBox()<br />&nbsp;</span><span style="color: #0000BB">00401022&nbsp; &nbsp;mov&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;esi</span><span style="color: #007700">,</span><span style="color: #0000BB">eax&nbsp; &nbsp; &nbsp;</span><span style="color: #FF8000">//&nbsp;保存返回值到变量&nbsp;iReturn&nbsp;。靠！变量&nbsp;iReturn&nbsp;自动使用&nbsp;ESI，编译器太聪明了：）<br />&nbsp;</span><span style="color: #0000BB">00401024&nbsp; &nbsp;push&nbsp; &nbsp; &nbsp; &nbsp; esi<br />&nbsp;00401025&nbsp; &nbsp;call&nbsp; &nbsp; &nbsp; &nbsp; dword&nbsp;ptr&nbsp;ds</span><span style="color: #007700">:[</span><span style="color: #0000BB">4050A0h</span><span style="color: #007700">]&nbsp;</span><span style="color: #FF8000">//&nbsp;调用&nbsp;MessageBeep()<br />&nbsp;</span><span style="color: #0000BB">0040102B&nbsp; &nbsp;mov&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;eax</span><span style="color: #007700">,</span><span style="color: #0000BB">esi&nbsp; &nbsp; &nbsp;</span><span style="color: #FF8000">//&nbsp;把变量&nbsp;iReturn&nbsp;交给&nbsp;EAX&nbsp;作为返回值<br />&nbsp;</span><span style="color: #0000BB">0040102D&nbsp; &nbsp;pop&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;esi&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #FF8000">//&nbsp;恢复要使用的重要寄存器<br />&nbsp;</span><span style="color: #0000BB">0040102E&nbsp; &nbsp;add&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;esp</span><span style="color: #007700">,</span><span style="color: #0000BB">24h&nbsp; &nbsp; &nbsp;</span><span style="color: #FF8000">//&nbsp;减少堆栈空间<br />&nbsp;</span><span style="color: #0000BB">00401031&nbsp; &nbsp;ret&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #FF8000">//&nbsp;堆栈长度减&nbsp;4&nbsp;并返回<br />&nbsp;</span><br />
</span><br />
</code></div><br />
<br />
这段代码虽然很精干&nbsp;(都能自动使用寄存器来保存变量了)，但是有的时候我们并不需要编译器提供这些自作主张的代码&nbsp;(比如写驱动程序的时候，不过我还没遇到过这种情况，呵呵~~)，我们希望整个全部函数都是自己亲手写进去的&nbsp;(BT&nbsp;呀^o^)。好，请出今天的主角&nbsp;——&nbsp;“naked”(怎么是裸体呀？)，<br />
C++&nbsp;的扩展关键字&nbsp;naked&nbsp;允许我们完全定制一个函数，废话不说了，看例子&nbsp;(熬夜写的&nbsp;Zzzzzz~~):<br />
<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_9l6WhQICl1Qj')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_9l6WhQICl1Qj);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_9l6WhQICl1Qj" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><code><span style="color: #000000"><br />
<span style="color: #0000BB">__declspec</span><span style="color: #007700">(</span><span style="color: #0000BB">naked</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">int&nbsp;Test</span><span style="color: #007700">()<br />&nbsp;{&nbsp;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp;__asm<br />&nbsp; &nbsp; &nbsp;</span><span style="color: #007700">{&nbsp;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;SUB&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ESP</span><span style="color: #007700">,</span><span style="color: #0000BB">24H<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUSH&nbsp; &nbsp; &nbsp; &nbsp; ESI<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;LEA&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;EAX</span><span style="color: #007700">,[</span><span style="color: #0000BB">ESP</span><span style="color: #007700">+</span><span style="color: #0000BB">4</span><span style="color: #007700">]<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;PUSH&nbsp; &nbsp; &nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUSH&nbsp; &nbsp; &nbsp; &nbsp; EAX&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUSH&nbsp; &nbsp; &nbsp; &nbsp; EAX&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUSH&nbsp; &nbsp; &nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MOV&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;BYTE&nbsp;PTR&nbsp;</span><span style="color: #007700">[</span><span style="color: #0000BB">ESP</span><span style="color: #007700">+</span><span style="color: #0000BB">14H</span><span style="color: #007700">],</span><span style="color: #0000BB">41H&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MOV&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;BYTE&nbsp;PTR&nbsp;</span><span style="color: #007700">[</span><span style="color: #0000BB">ESP</span><span style="color: #007700">+</span><span style="color: #0000BB">15H</span><span style="color: #007700">],</span><span style="color: #0000BB">0&nbsp; &nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CALL&nbsp; &nbsp; &nbsp; &nbsp; DWORD&nbsp;PTR&nbsp;</span><span style="color: #007700">[</span><span style="color: #0000BB">MessageBoxA</span><span style="color: #007700">]&nbsp;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;MOV&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ESI</span><span style="color: #007700">,</span><span style="color: #0000BB">EAX<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUSH&nbsp; &nbsp; &nbsp; &nbsp; ESI&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CALL&nbsp; &nbsp; &nbsp; &nbsp; DWORD&nbsp;PTR&nbsp;</span><span style="color: #007700">[</span><span style="color: #0000BB">MessageBeep</span><span style="color: #007700">]&nbsp;<br />&nbsp;</span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;MOV&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;EAX</span><span style="color: #007700">,</span><span style="color: #0000BB">ESI<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;POP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ESI<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ADD&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ESP</span><span style="color: #007700">,</span><span style="color: #0000BB">24H<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;RET<br />&nbsp; &nbsp; &nbsp; </span><span style="color: #007700">}<br />&nbsp;</span><span style="color: #0000BB"> </span><span style="color: #007700">}<br />&nbsp;</span><br />
</span><br />
</code></div><br />
<br />
上面的代码是使用的&nbsp;VC&nbsp;的内联汇编，和&nbsp;VC&nbsp;编译后生成的代码完全是一样的&nbsp;(很有完全控制的成就感吧^_^)。上面我们并没有又节省什么&nbsp;(节省的&nbsp;PUSH&nbsp;ECX&nbsp;并不是&nbsp;naked&nbsp;的功劳)，但是有的时候确实需要的&nbsp;(举不出例子来了，倒！)。最后随便说说注意事项:<br />
<br />
1.使用&nbsp;naked&nbsp;关键字需要自己构建&nbsp;EBP&nbsp;参数指针&nbsp;(如果用到了&nbsp;EBP&nbsp;作为参数指针的话)；<br />
2.必须自己使用&nbsp;RET&nbsp;或&nbsp;RET&nbsp;n&nbsp;指令返回&nbsp;(除非你不返回)。]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/147</link>
<title><![CDATA[#pragma 指示符应用举例]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2006-10-28 20:01:00</pubDate>
<guid>https://www.rickw.cn/blogview/147</guid>
	
<description><![CDATA[尽管&nbsp;C&nbsp;和&nbsp;C++&nbsp;都已经有标准，但是几乎每个编译器&nbsp;(广义，包含连接器等)&nbsp;扩展一些&nbsp;C/C++&nbsp;关键字。合理地应用这些关键字，有时候能使我们的工作非常方便。下面随便说说&nbsp;Visual&nbsp;C++&nbsp;中&nbsp;#pragma&nbsp;指示符的使用。<br />
一、用#pragma导出DLL函数<br />
<br />
传统的到出&nbsp;DLL&nbsp;函数的方法是使用模块定义文件&nbsp;(.def)，Visual&nbsp;C++&nbsp;提供了更简洁方便的方法，那就是“__declspec()”关键字后面跟“dllexport”，告诉连接去要导出这个函数，例如：<br />
<br />
<br />
__declspec(dllexport)&nbsp;int&nbsp;__stdcall&nbsp;MyExportFunction(int&nbsp;iTest);<br />
<br />
把“__declspec(dllexport)”放在函数声明的最前面，连接生成的&nbsp;DLL&nbsp;就会导出函数“_MyExportFunction@4”。<br />
<br />
上面的导出函数的名称也许不是我的希望的，我们希望导出的是原版的“MyExportFunction”。还好，VC&nbsp;提供了一个预处理指示符“#pragma”来指定连接选项&nbsp;(不仅仅是这一个功能，还有很多指示功能)&nbsp;，如下：<br />
<br />
<br />
#pragma&nbsp;comment(linker,"/EXPORT:MyExportFunction=_MyExportFunction@4")<br />
<br />
这下就天如人愿了：）。如果你想指定导出的顺序，或者只将函数导出为序号，没有&nbsp;Entryname，这个预处理指示符&nbsp;(确切地说是连接器)&nbsp;都能够实现，看看&nbsp;MSDN&nbsp;的语法说明：<br />
<br />
<br />
/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]<br />
<br />
@ordinal&nbsp;指定顺序；NONAME&nbsp;指定只将函数导出为序号；DATA&nbsp;关键字指定导出项为数据项。<br />
<br />
二、指示文件只包含一次<br />
<br />
在头文件中，一般在整个工程中我们只要包含一次就够了，但是如果我在多个&nbsp;.c/.cpp&nbsp;文件中都要包含着个头文件，比如&nbsp;Windows.h，那很多声明等等岂不是有两次了？解决这个问题的传统的方法是在头文件开始出用&nbsp;#define&nbsp;定义一个宏，比如&nbsp;Windows.h&nbsp;中:<br />
<br />
#ifndef&nbsp;_WINDOWS_<br />
&nbsp;#define&nbsp;_WINDOWS_<br />
<br />
然后在文件结为加上&nbsp;#endif，这样就可以避免被包含多次。但是这样的后果是代码的可读性较差&nbsp;(个人观点)，VC&nbsp;给我们提供了另外一个途径，那就是在文件的前面加上:<br />
<br />
<br />
<br />
<br />
<br />
<br />
#pragma&nbsp;once<br />
<br />
<br />
<br />
<br />
<br />
&nbsp; &nbsp; 是不是很方便？<br />
<br />
<br />
<br />
<br />
<br />
三、使警告无效<br />
<br />
<br />
<br />
<br />
&nbsp; &nbsp; 有时候我们不得不对变量进行强制转换，由此引来编译器的一番警告，特别是&nbsp;C++&nbsp;中，类型检查相对于&nbsp;C&nbsp;更为严格。这虽然不影响什么，但是看起来多不爽——我是故意要这样的，你警告什么！：）这时候你看到警告类型，比如“warning&nbsp;C4311:&nbsp;“类型转换”&nbsp;:&nbsp;从“HHOOK”到“BOOL”的指针截断”，在前面加上:<br />
<br />
<br />
<br />
<br />
<br />
<br />
#pragma&nbsp;warning(disable:&nbsp;4311)<br />
<br />
<br />
<br />
&nbsp; &nbsp;编译器就没话说了：）。<br />
<br />
<br />
<br />
<br />
<br />
四、指定连接要使用的库<br />
<br />
<br />
<br />
<br />
<br />
&nbsp; &nbsp; 比如我们连接的时候用到了&nbsp;WSock32.lib，你当然可以不辞辛苦地把它加入到你的工程中。但是我觉得更方便的方法是使用&nbsp;#pragma&nbsp;指示符，指定要连接的库:<br />
<br />
<br />
<br />
<br />
<br />
#pragma&nbsp;comment(lib,&nbsp;"WSock32.lib")<br />
<br />
<br />
<br />
<br />
<br />
五、显示编译消息<br />
<br />
<br />
&nbsp; &nbsp; &nbsp;没多少用处，举个例子吧:<br />
<br />
<br />
<br />
<br />
<br />
#ifdef&nbsp;_DEBUG<br />
&nbsp;#pragma&nbsp;message("编译连接为调试模式...")<br />
&nbsp;#endif&nbsp;//&nbsp;_DEBUG]]></description>
</item>
<item>
<link>https://www.rickw.cn/blogview/122</link>
<title><![CDATA[Debug 和 Release 编译方式的本质区别]]></title>
<author>rick</author>
<category>C\C++相关</category>
<pubDate>2006-07-13 12:54:45</pubDate>
<guid>https://www.rickw.cn/blogview/122</guid>
	
<description><![CDATA[Debug 通常称为调试版本，它包含调试信息，并且不作任何优化，便于程序员调试程序。Release 称为发布版本，它往往是进行了各种优化，使得程序在代码大小和运行速度上都是最优的，以便用户很好地使用。<br />
    Debug 和 Release 的真正秘密，在于一组编译选项。下面列出了分别针对二者的选项（当然除此之外还有其他一些，如/Fd /Fo，但区别并不重要，通常他们也不会引起 Release 版错误，在此不讨论）<br />
Debug 版本 <br />
 参数  含义 <br />
/MDd /MLd 或 /MTd 使用 Debug runtime library(调试版本的运行时刻函数库) <br />
/Od 关闭优化开关 <br />
/D "_DEBUG" 相当于 #define _DEBUG,打开编译调试代码开关(主要针对assert函数) <br />
/ZI 创建 Edit and continue(编辑继续)数据库，这样在调试过程中如果修改了源代码不需重新编译 <br />
/GZ 可以帮助捕获内存错误 <br />
/Gm 打开最小化重链接开关，减少链接时间 <br />
Release 版本 <br />
 参数  含义 <br />
/MD /ML 或 /MT 使用发布版本的运行时刻函数库 <br />
/O1 或 /O2 优化开关，使程序最小或最快 <br />
/D "NDEBUG" 关闭条件编译调试代码开关(即不编译assert函数) <br />
/GF 合并重复的字符串，并将字符串常量放到只读内存，防止被修改 <br />
    实际上，Debug 和 Release 并没有本质的界限，他们只是一组编译选项的集合，编译器只是按照预定的选项行动。事实上，我们甚至可以修改这些选项，从而得到优化过的调试版本或是带跟踪语句的发布版本。<br />
<br />
哪些情况下 Release 版会出错<br />
    有了上面的介绍，我们再来逐个对照这些选项看看 Release 版错误是怎样产生的<br />
1.  Runtime Library：链接哪种运行时刻函数库通常只对程序的性能产生影响。调试版本的 Runtime Library 包含了调试信息，并采用了一些保护机制以帮助发现错误，因此性能不如发布版本。编译器提供的 Runtime Library 通常很稳定，不会造成 Release 版错误；倒是由于 Debug 的  Runtime Library 加强了对错误的检测，如堆内存分配，有时会出现 Debug 有错但 Release 正常的现象。应当指出的是，如果 Debug 有错，即使 Release 正常，程序肯定是有 Bug 的，只不过可能是 Release 版的某次运行没有表现出来而已。<br />
 <br />
2.  优化：这是造成错误的主要原因，因为关闭优化时源程序基本上是直接翻译的，而打开优化后编译器会作出一系列假设。这类错误主要有以下几种：<br />
 1.   帧指针(Frame Pointer)省略（简称 FPO ）：在函数调用过程中，所有调用信息（返回地址、参数）以及自动变量都是放在栈中的。若函数的声明与实现不同（参数、返回值、调用方式），就会产生错误????但 Debug 方式下，栈的访问通过 EBP 寄存器保存的地址实现，如果没有发生数组越界之类的错误（或是越界“不多”），函数通常能正常执行；Release 方式下，优化会省略 EBP 栈基址指针，这样通过一个全局指针访问栈就会造成返回地址错误是程序崩溃。C++ 的强类型特性能检查出大多数这样的错误，但如果用了强制类型转换，就不行了。你可以在 Release 版本中强制加入 /Oy- 编译选项来关掉帧指针省略，以确定是否此类错误。此类错误通常有：<br />
 •  MFC 消息响应函数书写错误。正确的应为：afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam);<br />
ON_MESSAGE 宏包含强制类型转换。防止这种错误的方法之一是重定义 ON_MESSAGE 宏，把下列代码加到 stdafx.h 中（在#include "afxwin.h"之后）,函数原形错误时编译会报错。#undef ON_MESSAGE<br />
#define ON_MESSAGE(message, memberFxn) \<br />
{ message, 0, 0, 0, AfxSig_lwl, \<br />
(AFX_PMSG)(AFX_PMSGW)(static_cast&lt; LRESULT (AFX_MSG_CALL \<br />
CWnd::*)(WPARAM, LPARAM) &gt; (&amp;memberFxn) },<br />
 <br />
2.  volatile  型变量：volatile 告诉编译器该变量可能被程序之外的未知方式修改（如系统、其他进程和线程）。优化程序为了使程序性能提高，常把一些变量放在寄存器中（类似于 register 关键字），而其他进程只能对该变量所在的内存进行修改，而寄存器中的值没变。如果你的程序是多线程的，或者你发现某个变量的值与预期的不符而你确信已正确的设置了，则很可能遇到这样的问题。这种错误有时会表现为程序在最快优化出错而最小优化正常。把你认为可疑的变量加上  volatile 试试。<br />
 <br />
3.  变量优化：优化程序会根据变量的使用情况优化变量。例如，函数中有一个未被使用的变量，在  Debug 版中它有可能掩盖一个数组越界，而在 Release 版中，这个变量很可能被优化调，此时数组越界会破坏栈中有用的数据。当然，实际的情况会比这复杂得多。与此有关的错误有：<br />
 •   非法访问，包括数组越界、指针错误等。例如 void fn(void)<br />
{<br />
  int i;<br />
  i = 1;<br />
  int a[4];<br />
  {<br />
    int j;<br />
    j = 1;<br />
  }<br />
  a[-1] = 1;//当然错误不会这么明显，例如下标是变量<br />
  a[4] = 1;<br />
}<br />
                                    <br />
j 虽然在数组越界时已出了作用域，但其空间并未收回，因而 i 和 j 就会掩盖越界。而 Release 版由于 i、j 并未其很大作用可能会被优化掉，从而使栈被破坏。 <br />
 <br />
3.  _DEBUG 与 NDEBUG ：当定义了 _DEBUG 时，assert() 函数会被编译，而 NDEBUG 时不被编译。除此之外，VC++中还有一系列断言宏。这包括：<br />
 断言类型  定义 <br />
ANSI C 断言 void assert(int expression ); <br />
C Runtime Lib 断言 _ASSERT( booleanExpression );<br />
_ASSERTE( booleanExpression ); <br />
MFC 断言 ASSERT( booleanExpression );<br />
VERIFY( booleanExpression );<br />
ASSERT_VALID( pObject ); <br />
ASSERT_KINDOF( classname, pobject ); <br />
ATL 断言 ATLASSERT( booleanExpression ); <br />
 此外，TRACE() 宏的编译也受 _DEBUG 控制。<br />
  所有这些断言都只在 Debug版中才被编译，而在 Release 版中被忽略。唯一的例外是 VERIFY() 。事实上，这些宏都是调用了  assert() 函数，只不过附加了一些与库有关的调试代码。如果你在这些宏中加入了任何程序代码，而不只是布尔表达式（例如赋值、能改变变量值的函数调用 等），那么 Release 版都不会执行这些操作，从而造成错误。初学者很容易犯这类错误，查找的方法也很简单，因为这些宏都已在上面列出，只要利用 VC++ 的 Find in Files 功能在工程所有文件中找到用这些宏的地方再一一检查即可。另外，有些高手可能还会加入  #ifdef _DEBUG 之类的条件编译，也要注意一下。<br />
 顺便值得一提的是 VERIFY() 宏，这个宏允许你将程序代码放在布尔表达式里。这个宏通常用来检查 Windows API 的返回值。有些人可能为这个原因而滥用 VERIFY() ，事实上这是危险的，因为 VERIFY () 违反了断言的思想，不能使程序代码和调试代码完全分离，最终可能会带来很多麻烦。因此，专家们建议尽量少用这个宏。<br />
 <br />
4.  /GZ  选项：这个选项会做以下这些事： 1.  初始化内存和变量。包括用 0xCC 初始化所有自动变量，0xCD ( Cleared Data ) 初始化堆中分配的内存（即动态分配的内存，例如 new ），0xDD ( Dead Data ) 填充已被释放的堆内存（例如 delete ）， 0xFD( deFencde Data ) 初始化受保护的内存（debug 版在动态分配内存的前后加入保护内存以防止越界访问），其中括号中的词是微软建议的助记词。这样做的好处是这些值都很大，作为指针是不可能的（而且 32 位系统中指针很少是奇数值，在有些系统中奇数的指针会产生运行时错误），作为数值也很少遇到，而且这些值也很容易辨认，因此这很有利于在 Debug 版中发现 Release 版才会遇到的错误。要特别注意的是，很多人认为编译器会用 0 来初始化变量，这是错误的（而且这样很不利于查找错误）。<br />
 <br />
2.  通过函数指针调用函数时，会通过检查栈指针验证函数调用的匹配性。（防止原形不匹配）<br />
 <br />
3.  函数返回前检查栈指针，确认未被修改。（防止越界访问和原形不匹配，与第二项合在一起可大致模拟帧指针省略 FPO ）<br />
 <br />
<br />
 通常 /GZ 选项会造成 Debug 版出错而 Release 版正常的现象，因为 Release 版中未初始化的变量是随机的，这有可能使指针指向一个有效地址而掩盖了非法访问。<br />
 除此之外，/Gm /GF 等选项造成错误的情况比较少，而且他们的效果显而易见，比较容易发现。<br />
<br />
怎样“调试” Release 版的程序<br />
    遇到 Debug 成功但 Release 失败，显然是一件很沮丧的事，而且往往无从下手。如果你看了以上的分析，结合错误的具体表现，很快找出了错误，固然很好。但如果一时找不出，以下给出了一些在这种情况下的策略。<br />
1.   前面已经提过，Debug 和 Release 只是一组编译选项的差别，实际上并没有什么定义能区分二者。我们可以修改 Release 版的编译选项来缩小错误范围。如上所述，可以把 Release 的选项逐个改为与之相对的 Debug 选项，如 /MD 改为 /MDd、/O1 改为 /Od，或运行时间优化改为程序大小优化。注意，一次只改一个选项，看改哪个选项时错误消失，再对应该选项相关的错误，针对性地查找。这些选项在 Project \Settings... 中都可以直接通过列表选取，通常不要手动修改。由于以上的分析已相当全面，这个方法是最有效的。<br />
 <br />
2.  在编程过程中就要时常注意测试 Release 版本，以免最后代码太多，时间又很紧。<br />
 <br />
3.   在 Debug 版中使用 /W4 警告级别，这样可以从编译器获得最大限度的错误信息，比如 if( i =0 )就会引起 /W4 警告。不要忽略这些警告，通常这是你程序中的 Bug 引起的。但有时 /W4 会带来很多冗余信息，如 未使用的函数参数 警告，而很多消息处理函数都会忽略某些参数。我们可以用:#progma warning(disable: 4702) //禁止<br />
//...<br />
#progma warning(default: 4702) //重新允许来暂时禁止某个警告，或使用<br />
#progma warning(push, 3) //设置警告级别为 /W3<br />
//...<br />
#progma warning(pop) //重设为 /W4<br />
<br />
来暂时改变警告级别，有时你可以只在认为可疑的那一部分代码使用 /W4。<br />
 <br />
4.   你也可以像 Debug 一样调试你的 Release 版，只要加入调试符号。在 Project/Settings... 中，选中  Settings for "Win32 Release"，选中 C/C++ 标签，Category 选 General，Debug Info  选 Program Database。再在 Link 标签 Project options 最后加上 "/OPT:REF" (引号不要输)。这样调试器就能使用 pdb 文件中的调试符号。但调试时你会发现断点很难设置，变量也很难找到??这些都被优化过了。不过令人庆幸的是， Call Stack 窗口仍然工作正常，即使帧指针被优化，栈信息（特别是返回地址）仍然能找到。这对定位错误很有帮助。]]></description>
</item>
</channel>
</rss>